Count number of folders in directory and ignore shortcuts - powershell

I have a script which will accurately tell me how many folders are in a directory, and the subdirectories within. However, for one directory which I am working with, there are shortcut folders which seem to cause the script to fail.
Below is the error message which I receive:
Get-ChildItem : Could not find a part of the path 'C:\Folder\SubFolder\folder1\jpos'.
At C:\Desktop\Script Files\fileCount.ps1:34 char:10
+ $items = Get-ChildItem C:\Folder\SubFolder\ -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ReadError: (C:\Folder\SubFolder\folder1\jpos:String) [Get-ChildItem],
DirectoryNotFoundException
+ FullyQualifiedErrorId :
DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand`
The script runs fine for directories without shortcuts, but it seems to always fail when there are shortcuts within the directory.
Below is the code snippet for this section:
$items = Get-ChildItem C:\Folder\SubFolder -Recurse
$termFolder = ($items | Where-Object {$_.PSIsContainer}).count
Is there any way to skip over shortcuts or a better way to do a folder count?

(gci path |?{$_.Extension -ne ".lnk"}).Count
Shortcuts have .lnk extension and gci means Get-Childitem.

Just use -directory like this (for PowerShell 3 or +):
$items = Get-ChildItem C:\Folder\SubFolder -Recurse -Directory
$termFolder = $items.Count

If you don't need the directory collection folder subsequently in script, then you can simply use
$countDirs = $(Get-ChildItem -path c:\folder\subfolder -Recurse -Directory).count

Related

PowerShell 7Zip4Powershell zipping .zip error

Currently have a PSscript that does 1.65tb of .bmp files sorted into folders by yyyy/MM/dd/HH, replaces the # in the file name then converted to .jpg.
What I can't get past is the next step which gives me an error because it tries to zip the zip file that was created.
How to I prevent that? I tried the -Exclude but I think it has to be done just before the actual compression happens.
tried -Append and it fails for file not found.
(last step is delete the files that were zipped but I believe that can be done with a Remove-Item)
Directory structure looks like this with files in youngest child directory:
D:\Test\Processed\2020\01\13\13
D:\Test\Processed\2020\01\13\14
D:\Test\Processed\2020\01\13\15
D:\Test\Processed\2020\01\13\16
D:\Test\Processed\2020\01\13\17
D:\Test\Processed\2020\01\13\18
D:\Test\Processed\2020\01\13\19
D:\Test\Processed\2020\01\13\20
D:\Test\Processed\2020\01\13\21
D:\Test\Processed\2020\01\13\22
D:\Test\Processed\2020\01\13\23
PowerShell script
$sourceRootPath = "D:\Test\Processed\2020\01\13"
$targetRootPath = "D:\Test\Processed\2020\Archived"
Get-ChildItem -Path $sourceRootPath -Recurse -Exclude *.zip | Where-Object {$_.PSIsContainer} | ForEach-Object {
$directoryFullName = $_.FullName
$directoryName = $_.Name
#$folderPathToCompress - redundant but keeps my thinking straight for now
$folderPathToCompress = $directoryFullName
# This creates an error that the .zip file does not exist and exits
#Compress-7Zip -Path $folderPathToCompress -ArchiveFileName $directoryFullName\$directoryName.zip -Format Zip -CompressionLevel Ultra -Append
# This creates the .zip file BUT creates an error when it tries to zip the .zip file it is creating
#Compress-7Zip -Path $folderPathToCompress -ArchiveFileName $directoryFullName\$directoryName.zip -Format Zip -CompressionLevel Ultra
}
I will get this posting stuff figure out, sorry for the errors, I am open to learning two things at once but it takes 4x longer... so back at it.
1.) I am using the 7Zip4Powershell Module - it looked like a good idea, but maybe I should stick with passing everything to a variable and then Invoke-Expression thus not use the module but the 7zip command directly(?)
2.) Made a few attempts with same results but issue not resolved ... yet
This is what the error looks like and the different attempts below.
Compress-7Zip : The process cannot access the file 'D:\Test\Processed\2020\01\13\13\13.zip' because it is being used by another process.
At C:\Users\moe3srv\Desktop\test2.ps1:19 char:6
+ (Compress-7Zip -Path $folderPathToCompress -ArchiveFileName $dire ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (SevenZip4PowerS...+CompressWorker:CompressWorker) [Compress-7Zip], IOException
+ FullyQualifiedErrorId : err01,SevenZip4PowerShell.Compress7Zip
(Get-ChildItem -Path $sourceRootPath -Recurse)
(Get-ChildItem -Path $sourceRootPath -Recurse -Exclude .zip )
(Get-ChildItem -Path $sourceRootPath -Recurse -Exclude *.zip )
Alternatively in PowerShell we can user Compress-Archive
eg,
Compress-Archive -Path C:\Reference\* -DestinationPath C:\Archives\Draft.zip

Rename file before copy to certain folder

I´m a newbie still and learning to create PowerShell scripts to make Life in IT easier.
At present I´m trying to build a script, which runs a certain Microsoft tool, scanning defined network shares in a csv file and creating an JSON output file.
Now as the pattern of this file is always the same like "Report_Username_Hostname.vba.JSON", I would like to append either the scanned directory name or even a range of numbers, fe. "Report_Username_Hostname(100).vba.JSON" or "Report_Username_Hostname(sharename).vba.JSON"
This is neccessaray as after this renaming step, I upload this and other files within this folder to another folder on different server to upload them into a Database.
I planned to run this script in in many different locations on most automatic level and they all copy the their collected files to just one upload folder.
I already tried several options I found somewhere in the deep of the Internet, but I only came to the point where the file was renamed to 0 or similar, but not to expected result.
The Powershell script doing the work is this:
$PSpath = 'C:\temp\FileRemediation\Scripts\'
$Rpath = $PSpath +'..\Reports\1st'
$localshare = $PSpath +'..\temp\1st'
$csvinputs = Import-Csv $PSpath\fileremediation_1st.csv
$uploadshare = '\\PGC2EU-WFSFR01.eu1.1corp.org\upload\'
# This section checks if the folder for scan reports is availabe and if not will create necessary folder.
If(!(test-path $Rpath))
{
New-Item -ItemType Directory -Force -Path $Rpath
}
If(!(test-path $localshare))
{
New-Item -ItemType Directory -Force -Path $localshare
}
Set-Location $Rpath
# This section reads input from configuration file and starts Ms ReadinessReportCreator to scan shares in configuration file.
ForEach($csvinput in $csvinputs)
{
$uncshare = $csvinput.sharefolder
$Executeable = Start-Process "C:\Program Files (x86)\Microsoft xxx\xxx.exe" `
-Argumentlist "-p ""$uncshare""", "-r", "-t 10000", "-output ""$localshare"""`
-Wait
Get-ChildItem -Path $localshare -Filter '*.JSON' | Rename-Item -NewName {$_.FullName+$uncshare}
}
# This section copies the output *.JSON file of the xxx to the share, where I they will be uploaded to DB.
Get-ChildItem -Path $localshare -Filter '*.JSON' | Where {$_.Length -ge 3} | move-item -Destination '$uploadshare'
the fileremediation_1st.csv looks like
sharefolder
\\server\sharename
Can someone please help me on this, I don´t have a clue what I´m doing wrong.
Thank you!
Current error I get is
Rename-Item : Cannot rename the specified target, because it
represents a path or device name. At
C:\temp\FileRemediation\scripts\fileremediation_V2_1st.ps1:28 char:55
+ ... share -Filter '*.JSON' | Rename-Item -NewName {$_.FullName+$uncshare}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
As said before, I would also be fine with a dedicated range of numbers, which is append to the file name "Report_Username_Hostname(100).vba.JSON"
The perfect world would be if I could split the \server\sharename from csv file and append the sharename to my filename.
I think the issue is with:
Rename-Item -NewName {$_.FullName+$uncshare}
Your input file (Get-ChildItem) path is:
$PSpath = 'C:\temp\FileRemediation\Scripts\'
$localshare = $PSpath +'..\temp\1st'
The Rename-Item uses $_.FullName which resolves to something like this:
C:\temp\FileRemediation\Scripts\..\temp\1st\MyFile.JSON
The variables then contain:
$_.FullName = C:\temp\FileRemediation\Scripts\..\temp\1st\MyFile.JSON
$uncshare = "\\server\sharename"
So Your Rename-Item ... $_.FullName+$uncshare will try to rename it to:
C:\temp\FileRemediation\Scripts\..\temp\1st\MyFile.JSON\\server\sharename
Which is not a valid path.

Deleting log files that are buried with powershell

So I am trying to figure out a script to delete log files that are buried in many folders. Same path to the end folder minus the client name folder that changes. Below is an example of the code I thought would work which is failing horribly. Any advice would be appreciated.
gci X:\ -directory -recurse | ?{$_.FullName -match \\temp\\company\\.+?\\AppData\\logfiles -and $_.CreationTime -lt (get-date).AddDays(-20)}|Remove-Item -recurse -whatif
so the Directory is X and the path to the logfiles that I want to delete is temp\company\NAME\appdata\logfiles and the NAME folder is the one that could be one of any number of different clients names.
Error I keep getting.
At line:1 char:51
+ gci X:\ -directory -recurse | ?{$_.FullName -match \\temp\\company\\.+?\\ ...
+ ~
You must provide a value expression on the right-hand side of the '-match' operator.
At line:1 char:52
+ gci x:\ -directory -recurse | ?{$_.FullName -match \\Temp\\company\\.+?\\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token '\\Temp\\company\\.+?\\AppData\\logfiles' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ExpectedValueExpression
Does anyone have any ideas what we are doing wrong or how to accomplish this goal?
Thanks in advance!
The errors are because second argument to -match needs to be in quotes.
But there may be a way to do this without needing the complexity of your example. Get-ChildItem can take both a -Path and a -Include (or -Filter) argument. So you might use something like this:
Get-ChildItem -path c:\xxx -Include *log.tmp -Recurse | ... | Remove-Item

I need to remove folders by a specific name, if it exist

I have a file server where the users have their own diskspace. And I need to delete a certain folder on each users diskspace, but not all users have this folder. Also the users are divided into department, so the layout of the folders looks like this:
D:\users\departmentA\usernameA\foldertodelete
D:\users\departmentA\usernameB\foldertodelete
D:\users\departmentB\usernameC\foldertodelete
D:\users\departmentC\usernameD\foldertodelete
...
How can I make this happen? Im thinking of using Poweshell, and I have been reading about Test-Path, but I dont know how to work with this then the path is different for all the users.
This is fairly straightforward with PowerShell:
$TargetName = "foldertodelete"
$BaseDir = "D:\Users"
# Iterate over each department directory
foreach($Department in #(Get-ChildItem $BaseDir -Directory)){
# Within each department, iterate over each user directory
foreach($User in #(Get-ChildItem $Department -Directory)){
# Check if the undesirable folder exists
if([System.IO.Directory]::Exists(($TargetPath = Join-Path -Path $User -ChildPath $TargetName))){
# If so, remove the directory and all child items
Remove-Item $TargetPath -Recurse
}
}
}
The -Directory parameter on Get-ChildItem is available in PowerShell 3.0 and above. For PowerShell 2.0 you could use:
Get-ChildItem $BaseDir |Where {$_.PSIsContainer}
Thank you for your answer. I do have some problem making the script work. It looks like the script don't understand the BaseDir part. The department folder where the users have their folder is located on D:\Users. I copied the script to C:\skript. And the error message show that it is looking for the userfolder on my C drive. It should look on D:\users\AAL-users\username
Here is the error message:
PS C:\skript> .\RemoveFolder.ps1
Get-ChildItem : Cannot find path 'C:\skript\AAL-users' because it does not exist.
At C:\skript\RemoveFolder.ps1:7 char:22
+ foreach($User in #(Get-ChildItem $Department -Directory)){
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\skript\AAL-users:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
I did try to copy the script to my D:\users folder. This time I got no error messages, but the script did not delete any folders as it is suposed to.
Try the below...
Remove-Item -path D:\Users\* -Filter *specificnameof the folder* -WhatIf --(Whatif allows you to test a command before you run)
Remove whatif and execute the delete
Remove-Item -path C:\users\* -Filter *specificnameof the folder*
Here is the exact code I run now:
PS D:> Remove-Item -path "D:\DU Users*" -Filter notes85
PS D:>
No error messages, but also, the folder in question is not removed.

Parsing Shortcuts in Powershell

I have some code which is trying to make a copy of a directory which contains shortcuts:
# Create a directory to store the files in
mkdir "D:\backup-temp\website.com files\"
# Search for shortcuts so that we can exclude them from the copy
$DirLinks = Get-ChildItem "\\web1\c$\Web Sites\website\" -Recurse | ? { $_.Attributes -like "*ReparsePoint*" } | % { $_.FullName }
# Execute the copy
cp -recurse -Exclude $DirLinks "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
But when I execute the script I get the following error:
Copy-Item : The symbolic link cannot be followed because its type is disabled.
At C:\scripts\backup.ps1:16 char:3
+ cp <<<< -recurse "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId :
System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
It seems the script is getting hung up on a symbolic link (I'm assuming the shortcut) that I'm trying to exclude in the fourth line of the script.
How can I tell powershell to ignore/exclude shortcuts?
Thanks,
Brad
If you are on V3 or higher you can eliminate the reparse points like so:
Get-ChildItem "\\web1\c$\Web Sites\website" -Recurse -Attributes !ReparsePoint |
Copy-Item -Dest "D:\backup-temp\website.com files"
On V1/V2 you can do this:
Get-ChildItem "\\web1\c$\Web Sites\website" |
Where {!($_.Attributes -bor [IO.FileAttributes]::ReparsePoint)} |
Copy-Item -Dest "D:\backup-temp\website.com files" -Recurse
So it turns out that the issue I faces is explained in this Microsoft Blog Post:
http://blogs.msdn.com/b/junfeng/archive/2012/05/07/the-symbolic-link-cannot-be-followed-because-its-type-is-disabled.aspx
Essentially on the server I am running the powershell script from I needed to run the following command:
fsutil behavior set SymlinkEvaluation R2R:1
This allows Remote to remote symbolic links. Once this is in place the above powershell commands run as expected without errors.