2013-07-01 3 views
2

Я пишу сценарий PowerShell, который удаляет все, кроме X самых последних папок, за исключением папки с именем Data. Мое заявление, чтобы собрать папки для удаления выглядит так:PowerShell Get-ChildItem и Skip

$folders1 = Get-ChildItem $parentFolderName | 
    ? { $_.PSIsContainer -and $_.Name -ne "Data" } | 
    sort CreationTime -desc | 
    select -Skip $numberOfFoldersToKeep 

foreach ($objItem in $folders1) { 
    Write-Host $webServerLocation\$objItem 
    Remove-Item -Recurse -Force $parentFolderName\$objItem -WhatIf 
} 

Это прекрасно работает, когда я прохожу $numberOfFoldersToKeep, которое меньше, чем количество папок в исходном каталоге $parentFolderName. Например, с 5 подкаталогов в моей целевой папке, это работает, как ожидалось:

myScript.ps1 C:\StartingFolder 3 

Но если бы я должен был передать большое количество папок пропускаемых, мое заявление, кажется, возвращает значение самого $parentFolderName! Так что это не будет работать:

myScript.ps1 C:\StartingFolder 15 

Поскольку переменный пропуск превышает число элементов в Get-ChildItem коллекции, скрипт пытается удалить C:\StartingFolder\, который не был, что я ожидал вообще.

Что я делаю неправильно?

+1

Почему бы не включить ваш foreach в оператор IF: 'if ($ folder1 -neq $ null) {...} ...' или просто использовать 'remove-item $ objectItem.fullname' –

+0

Я не могу воспроизвести это. Если я передаю '$ numberOfFoldersToKeep' с числом, большим, чем результат' gci', переданным через '?', Я возвращаю '$ null' (и поэтому' foreach' даже не выполняется), что точно, что я ожидаю. – alroc

+0

@alroc Посмотрите, как он удаляет файл;) –

ответ

2

попробовать это:

$folders1 = Get-ChildItem $parentFolderName | 
    ? { $_.PSIsContainer -and $_.Name -ne "Data" } | 
    sort CreationTime -desc | 
    select -Skip $numberOfFoldersToKeep 
    if ($folder1 -neq $null) 

{ 

foreach ($objItem in $folders1) { 


     Write-Host $($objItem.fullname) 




Remove-Item -Recurse -Force $objItem.fullname -WhatIf 
    } 
    } 
+0

Этот нулевой тест очень важен! Спасибо за вашу помощь. Я понятия не имел, что тело foreach будет выполнено, если сбор, переданный в foreach, был нулевым. – dthrasher

+0

Это как ошибка. Прочитайте мой последний комментарий к вашему вопросу. –

1

Я дал @ C.B. кредит для ответа, но есть еще один способ решить проблему, заставив вывод Get-ChildItem массиву с использованием синтаксиса @(...).

$folders1 = @(Get-ChildItem $parentFolderName | 
    ? { $_.PSIsContainer -and $_.Name -ne "Data" } | 
    sort CreationTime -desc | 
    select -Skip $numberOfFoldersToKeep) 

foreach ($objItem in $folders1) { 
    Write-Host $webServerLocation\$objItem 
    Remove-Item -Recurse -Force $parentFolderName\$objItem -WhatIf 
} 

Это возвращает массив нулевой длины, поэтому тело оператора foreach не выполняется.

Как отмечалось C.B. в приведенных выше замечаний, проблема заключается в том, что если вы передаете null коллекцию в Еогеасп заявление в PowerShell, тело заявления Еогеасп выполняется один раз.

Это было совершенно неинтуитивно для меня, исходя из фона .NET. По-видимому, это неинтересно для многих других людей, так как есть сообщения об ошибках, поданные для такого поведения в MSDN: https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=281908&SiteID=99

По-видимому, эта ошибка исправлена ​​в PowerShell V3.