PowerShell — самый компактный способ удалить все файлы из этой папки, кроме одного

Каков самый компактный способ удаления всех файлов из папки, кроме одного файла в сценарии PowerShell. Мне совершенно неважно, какой файл хранится, лишь бы был один.

Я использую PowerShell 2 CTP.

ОБНОВЛЕНИЕ:
объединение всех ответов на данный момент...

$fp = "\\SomeServer\SomeShare\SomeFolder"
gci $fp |where {$_.mode -notmatch "d"} |sort creationtime -desc |select -last ((@(gci $fp)).Length - 1) |del 

Кто-нибудь видит какие-либо проблемы с использованием этого? Как насчет части -notmatch?


person BuddyJoe    schedule 20.02.2009    source источник
comment
У меня нет проблем с проверкой -noMatch как таковой. Я думаю, что более подходящим для PS способом было бы where{ -not $_.PSIsContainer }   -  person EBGreen    schedule 23.02.2009


Ответы (5)


В PS V2 мы добавили -SKIP для выбора, чтобы вы могли:

реж | где {$_.mode -notmatch "d"} |select -skip 1 |del

person Jeffrey Snover - MSFT    schedule 21.02.2009
comment
Похоже, это может быть отличным хранилищем формализованного фольклора. - person Jeffrey Snover - MSFT; 22.02.2009

Без каких-либо встроенных функций это немного запутанно, потому что функции должны иметь дело с определенной длиной. Но вы можете сделать это таким образом, который включает в себя просмотр каталога дважды.

gci $dirName | select -last ((@(gci $dirName)).Length-1) | del

Я написал несколько расширений powershell, которые значительно упрощают такие задачи. Одним из примеров является Skip-Count, который позволяет пропускать произвольное количество элементов в конвейере. Таким образом, код можно быстро найти, чтобы просмотреть каталог только один раз.

gci $dirName | skip-count 1 | del

Источник для пропуска счетчика: http://blogs.msdn.com/jaredpar/archive/2009/01/13/linq-like-functions-for-powershell-skip-count.aspx

ИЗМЕНИТЬ

Чтобы убить папки, используйте «rm -re -fo» вместо «del».

ИЗМЕНИТЬ2

Чтобы избежать всех папок (пустых или нет), вы можете изменить код как таковой.

gci $dirName | ?{ -not $_.PSIsContainer } | skip-count 1 | del

Элемент PSISContainer верен только для папок.

person JaredPar    schedule 20.02.2009
comment
@EBGreen, нет, но я добавил Edit, чтобы указать, как заставить его убивать папки. - person JaredPar; 20.02.2009
comment
JaredPar, что именно мешает удалить папки? Смотрите мои последние комментарии к ответу zdans. - person BuddyJoe; 20.02.2009
comment
@Bruno, по умолчанию del не удаляет непустую папку. - person JaredPar; 20.02.2009

как насчет:

dir $dirName | select -first ((dir $dirName).Length -1) | del

удаляет все, кроме последнего.

Редактировать. Более гибкая версия, к тому же вам не нужно дважды вводить команду dir:

$include=$False; dir $dirNam | where {$include; $include=$True;} | del

Обратите внимание, что это делает обратное, удаляет все, кроме первого. Это также позволяет вам добавлять пункты, например, чтобы не действовать в каталогах:

$include=$False; dir $dirNam | where {$include -and $_.GetType() -ne [System.IO.DirectoryInfo]; $include=$True;} | del

Редактировать 2 в отношении исключения каталогов с использованием свойства Mode. Я предполагаю, что это должно работать при условии, что фреймворк не изменит способ генерации строки режима (я не могу представить, что это произойдет). Хотя я мог бы ужесточить регулярное выражение до:

$_.Mode -notmatch "^d.{4}"

Если вы пытаетесь не печатать, лучше всего добавить функцию в свой профиль:

function isNotDir($file) { return $file.GetType() -ne [System.IO.DirectoryInfo];}
dir $dirName | where {isNotDir($_)}
person zdan    schedule 20.02.2009
comment
Как вы можете указать путь и сделать все это одной строкой кода? - person BuddyJoe; 20.02.2009
comment
имейте в виду, что это также удалит папки. - person EBGreen; 20.02.2009
comment
Я отредактировал это с более гибким решением, которое позволит вам пропускать папки. - person zdan; 20.02.2009
comment
+1. Мне нравится, к чему это ведет, особенно $_.GetType() -ne [System.IO.DirectoryInfo]. Но когда я пытаюсь использовать его, я получаю сообщение об ошибке (ниже) - person BuddyJoe; 20.02.2009
comment
Вы не можете вызвать метод для выражения с нулевым значением. + gci $dirName |where-object $_.GetType ‹‹‹‹ () -ne [System.IO.DirectoryInfo] + CategoryInfo: InvalidOperation: (GetType:String) [], RuntimeException + FullyQualifiedErrorId: InvokeMethodOnNull - person BuddyJoe; 20.02.2009
comment
будет ли это работать |where-object {$_.mode -notmatch d} или это иногда будет ломаться - person BuddyJoe; 20.02.2009
comment
@ Бруно Тиндалл: я думаю, вы забыли фигурные скобки для предложения where-object. - person zdan; 20.02.2009
comment
Как упоминалось в другом ответе, вероятно, было бы лучше использовать $_.PSIsContainer. Также не забывайте об операторе -is: $_ -is [System.IO.DirectoryInfo] - person JasonMArcher; 22.02.2009

Мое любимое:

move file to preserve elsewhere
delete all files
move preserved file back
person Joshua    schedule 21.02.2009

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

Это приведет к удалению всех файлов, кроме самых последних созданных.

person Chris Ballance    schedule 20.02.2009
comment
Я думаю, что оставит папку, которая является более новой, чем все файлы. - person EBGreen; 20.02.2009
comment
хм. Придется оставить один файл. Папки/подпапки должны оставаться нетронутыми. - person BuddyJoe; 20.02.2009