Reputation: 71101
What is the most compact way of deleting all files from a folder except one file in a PowerShell script. I doesn't matter at all which file is kept, just as long as one is kept.
I'm using the PowerShell 2 CTP.
UPDATE:
An amalgamation of all the answers so far...
$fp = "\\SomeServer\SomeShare\SomeFolder"
gci $fp |where {$_.mode -notmatch "d"} |sort creationtime -desc |select -last ((@(gci $fp)).Length - 1) |del
Anybody see any issues with using this? How about the -notmatch part?
Upvotes: 3
Views: 4518
Reputation: 10253
In PS V2 we added -SKIP
to Select so you could do:
dir | where {$_.mode -notmatch "d"} |select -skip 1 |del
Upvotes: 10
Reputation: 43280
My favorite:
move file to preserve elsewhere
delete all files
move preserved file back
Upvotes: 1
Reputation: 29450
how about:
dir $dirName | select -first ((dir $dirName).Length -1) | del
deletes all but the last one.
Edit: A more flexible version, plus you won't have to enter the dir command twice:
$include=$False; dir $dirNam | where {$include; $include=$True;} | del
Note, this does the opposite, it deletes all but the first. It also allows you to add clauses, such as to not act on directories:
$include=$False; dir $dirNam | where {$include -and $_.GetType() -ne [System.IO.DirectoryInfo]; $include=$True;} | del
Edit 2 with regards to excluding directories using the Mode property. I guess that should work provided that the framework does not change the way the mode string is generated (I can't imagine it will). Though I might tighten up the regular expression to:
$_.Mode -notmatch "^d.{4}"
If you are trying to avoid typing, adding a function to your profile is your best bet:
function isNotDir($file) { return $file.GetType() -ne [System.IO.DirectoryInfo];}
dir $dirName | where {isNotDir($_)}
Upvotes: 1
Reputation: 754745
Without any built-in functions it is a little bit convoluted because the functions neeed to deal with definitive length. But you can do it this way which involves looking at the directory twice
gci $dirName | select -last ((@(gci $dirName)).Length-1) | del
I wrote several powershell extensions that make tasks like this a lot easier. One example is Skip-Count which allows for an arbitrary number of elements to be skipped in the pipeline. So the code can be quickly searched to only look at the directory once
gci $dirName | skip-count 1 | del
Source to Skip-Count: http://blogs.msdn.com/jaredpar/archive/2009/01/13/linq-like-functions-for-powershell-skip-count.aspx
EDIT
In order to kill folders use "rm -re -fo" instead of "del"
EDIT2
In order to avoid all folders (empty or not) you can modify the code as such
gci $dirName | ?{ -not $_.PSIsContainer } | skip-count 1 | del
The PSISContainer member is only true for folders.
Upvotes: 5
Reputation: 34347
del . -Exclude (dir | sort creationtime -desc)[0] -whatif
This will delete all files except the most recently created.
Upvotes: 0