I have a directory containing a load of subdirectories and files. I need to delete all files except those under SubFolder1.
Initial State: Desired Output:
\ \
|_Folder1 |_Folder1
| |_File1.txt |_SubFolder1
| |_File2.xml |_File3.csv
| |_SubFolder1 |_File4.exe
| | |_File3.csv
| | |_File4.exe
| |_Subfolder2
|_Folder2
| |_ <more files here>
|_Folder3 (etc)
So here's what I tried:
Remove-Item * -exclude Folder1\Subfolder1\*
And I get a warning like this:
Confirm
The item at C:\foo\Folder1 has children and the -recurse parameter was not specified.
If you continue, all children will be removed with the item. Are you sure you want to continue?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "Y"):
When I specify -recurse
, it deletes every file, and seems to ignore my filters.
What's going on, and what's the correct way of doing this?
Edit: I've included a zip file which contains an example folder structure as above. If you want to test a solution, please try it against there. I've also included a second zip file which has the desired output, so you can check if it's working.
(Get-ChildItem c:\folder1\ -recurse | select -ExpandProperty fullname) -notlike 'c:\folder1\subfolder1*' | sort length -descending | remove-item
Maybe there's a simpler solution, but this function should do the trick:
function Clean-Folder
{
param(
[string]$rootfolder,
[string[]]$excluded
)
$rootfolder = resolve-path $rootfolder
Push-Location $rootFolder
if($excluded -notmatch "^\s*$")
{
$excluded = Resolve-Path $excluded
}
$filesToDel = Get-ChildItem $rootFolder -Recurse
# Excluding files in the excluded folder
foreach($exclusion in $excluded)
{
$filesToDel = $filesToDel |?{$_.fullname -notlike ("{0}\*" -f $exclusion)}
# Excluding parent folders of the excluded folder
while($exclusion -notmatch "^\s*$")
{
$filesToDel = $filesToDel |?{$_.fullname -ne $exclusion}
$exclusion = Split-Path -parent $exclusion
}
}
$filesToDel |Remove-Item -Recurse -ErrorAction SilentlyContinue
Pop-Location
}
Basically, what it does is recursively list all the items in your folder, then remove the one you want to keep, its sub-items and all its parent folders. Finally, it deletes the remaining list.
Just declare the function above, then:
Clean-Folder -rootfolder <path> -excluded <folder you want to exclude>
Edit: made rootfolder accept relative paths, and excluded accept a list of folders
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With