Reputation: 8977
I have a folder structure that looks like:
C:\RootFolder
\file1.txt
\file2.txt
\license.txt
\Settings
\fileA.txt
\fileB.txt
\settings.txt
\OtherFolders
Delete all of the files except for license.txt and settings.txt.
I would like in the end for only the following to remain:
C:\RootFolder
\license.txt
\Settings
\settings.txt
$exclude = @('license.txt', 'settings.txt')
Get-ChildItem C:\RootFolder -recurse -exclude $exclude | foreach ($_) {remove-item $_.fullname -recurse:$false}
Even though I specify -recurse:$false specifically, it always generates a message for each folder indicating that "recurse isn't specified" and saying it will delete all child items.
After this, the license.txt file remains, but the settings.txt file (in a subdirectory) does not.
Upvotes: 1
Views: 8324
Reputation: 8977
And almost as soon as I posted, the answer came to me -- I had to find only files, not directories.
Since I'm on PowerShell 2.0, I couldn't use the -File attribute that's new in powershell 3. Instead, I have to check every object to see if it's a container.
$exclude = @('license.txt', 'settings.txt')
Get-ChildItem C:\RootFolder -recurse -exclude $exclude | Where-Object {!($_.PSIsContainer)} | foreach ($_) {remove-item $_.fullname}
This worked perfectly to achieve what I needed.
Thanks to several comments / posts here, there are some more elegant ways that taught me a bit more about powershell:
Given these, an elegant solution that fits into a one-liner would be:
gci C:\RootFolder -Recurse -Exclude @('license.txt', 'settings.txt') | ? { ! $_.PSIsContainer } | Remove-Item -Force
Upvotes: 3
Reputation: 306
You code works great.
Just a one-liner so we can do it another way:
Get-ChildItem C:\RootFolder -recurse | Where-Object {!($_.PSIsContainer)} | Foreach { if ( $_.Name -ne "license.txt" -and $_.Name -ne "settings.txt") {remove-item $_.FullName -force}}
If there are a lot of files need to be excluded then this one liner doesn't scale - in that case I will use your code:)
@Sean Killeen by the way: Is there a ($_) after foreach? Sounds like you are using Foreach-Object Cmdlet instead of Foreach construct. My understanding is for Cmdlet we don't need ($something in $sometingElse) after "foreach-object". But in Foreach construct we need ($something in $somethingElse). Correct me if I am wrong.
Upvotes: 1