BuddyJoe
BuddyJoe

Reputation: 71101

PowerShell - Most Compact way of "Delete all files from this folder except one"

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

Answers (6)

Jeffrey Snover - MSFT
Jeffrey Snover - MSFT

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

murfman
murfman

Reputation: 11

How about:

dir $fp -Exclude "d" | del

Upvotes: 1

Joshua
Joshua

Reputation: 43280

My favorite:

move file to preserve elsewhere
delete all files
move preserved file back

Upvotes: 1

zdan
zdan

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

JaredPar
JaredPar

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

Chris Ballance
Chris Ballance

Reputation: 34347

del . -Exclude (dir | sort creationtime -desc)[0] -whatif

This will delete all files except the most recently created.

Upvotes: 0

Related Questions