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

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.

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.

What command line to delete folder in Appdata folder for local user?

I am trying to test a script to delete a folder in APPdata local folder for a user on machine but testing it locally on my test machine. i cannot use the %userprofile% so technically need to delete a test folder at c:/users/testusername/appdata/local/test
Whats the correct command to delete folders or files from a local user account? I don't want to use the exact name of user.
Also for power shell if i want to delete folders that begin with test_foldername is there a way i can wild card to delete anything with "test_"?
Thanks
Ended up using the following
$users = Get-ChildItem C:\Users
foreach ($user in $users){$folder = "$($user.fullname)\AppData\Local\Test"
If (Test-Path $folder) {Remove-Item $folder -Recurse -Force -ErrorAction silentlycontinue } }
Get-Childitem -Directory -Path $env:LOCALAPPDATA | where {$_.Name -like 'test_*'} | Remove-Item -Force -Recurse -WhatIf
Remove the -WhatIf to actual perform the delete
$env:LOCALAPPDATA will refer to the oaming app data location for the user running the script

Count number of folders in directory and ignore shortcuts

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

PowerShell remove-item succeeds but throws exception

I'm running the following command in a directory that is the root of a Mercurial repository. I want to delete any files and folders beginning with ".hg":
gci -rec -filter ".hg*" | remove-item -recurse -force
The strange thing, is that it does actually work, but still produces the following exception:
Get-ChildItem : Could not find a part of the path 'C:\temp\WSCopyTest\MyCompany.Services.DaftPunk\.hg\'.
At line:1 char:4
+ gci <<<< -rec -filter ".hg*" | remove-item -recurse -force
+ CategoryInfo : ReadError: (C:\temp\WSCopyT...es.DaftPunk\.hg:String) [Get-ChildItem], DirectoryNotFoundException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
Because the exception is thrown by Get-ChildItem, I suspect my understanding of the pipelining in PowerShell is flawed. Almost like Get-ChildItem finds an item, passes it to the next cmdlet in the pipeline, then looks for the next one? Is that how it works?
The following was supposed to be a script that would replicate the problem, but, on the same machine, it works flawlessly:
$repoRoot = "C:\Temp\HgDeleteTest\MyRepo"
remove-item $repoRoot -recurse -force
md $repoRoot
pushd $repoRoot
hg.exe init
add-content ShouldBeLeftBehind.txt "This is some text in a file that should be left behind once the various .hg files/directories are removed."
add-content .hgignore syntax:glob
add-content .hgignore *.dll
add-content .hgignore *.exe
hg.exe commit --addremove --message "Building test repository with one commit."
gci -rec -filter ".hg*" | remove-item -recurse -force
popd
Could it be that you're removing a folder starting with .hg, which in turn contains a file starting with .hg, but that file no longer exists?
I expect Antony is correct - using the -recurse on the gci will enumerate both files and directories that match ".hg*". The directory will be returned first. Then remove-item deletes the directory first, and the -force switch deletes all the files in it. Then it tries to delete the files that were in that directory that match ".hg*" (that were there when the gci ran) but they're gone now. This should stop the errors:
gci ".hg*" -recurse | select -expand fullname | sort length -desc | remove-item -force
Sorting the full names in descending order of length insures that no matched parent directory is deleted before all the matched files in that directory are deleted.
The following will restrict its deletions to files only, and exclude folders.
gci -rec -filter ".hg*" | Where {$_.psIsContainer -eq $false} | remove-item -recurse -force
Then run it again, by deleting the folders:
gci -rec -filter ".hg*" | Where {$_.psIsContainer -eq $true} | remove-item -recurse -force
I ended up separating the search from the removal. I believe my issue was to do with the way piping works by default (i.e. one item at a time) but I've not been able to build a test to check it.
In any case, the following works fine:
$hgObjects = gci -rec | ?{ $_.name -like ".hg*" -and $_.name -ne ".hgignore" }
remove-item $hgObjects -force -recurse
Using this style, the remove-item cmdlet gets an array of items found and works through them.
The .hg folder in my original example didn't have anything in it called .hg*, so I don't see what was going on. It felt more like it was trying to delete the folder twice, which I find very strange. I wonder if it's actually a PowerShell manifestation of this standard .NET behaviour:
An enumerator remains valid as long as the collection remains
unchanged. If changes are made to the collection, such as adding,
modifying or deleting elements, the enumerator can be invalidated and
the next call to MoveNext or Reset can throw an
InvalidOperationException. If the collection is modified between
MoveNext and Current, Current returns the element that it is set to,
even if the enumerator is already invalidated.
(Taken from http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator(v=vs.71).aspx).