PowerShell удалить элемент успешно, но выдает исключение - PullRequest
1 голос
/ 20 июля 2011

Я запускаю следующую команду в каталоге, который является корнем хранилища Mercurial. Я хочу удалить любые файлы и папки, начинающиеся с ".hg":

gci -rec -filter ".hg*" | remove-item -recurse -force

Странно то, что он действительно работает, но все равно выдает следующее исключение:

Get-ChildItem : Could not find a part of the path 'C:\temp\WSCopyTest\MyCompany.Services.DaftPunk\.hg\'.
At line:1 char:4
+ gci <<<<  -rec -filter ".hg*" | remove-item -recurse -force
    + CategoryInfo          : ReadError: (C:\temp\WSCopyT...es.DaftPunk\.hg:String) [Get-ChildItem], DirectoryNotFoundException
    + FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand

Поскольку исключение выдается Get-ChildItem, я подозреваю, что мое понимание конвейеризации в PowerShell неверно. Почти как Get-ChildItem находит элемент, передает его следующему командлету в конвейере, а затем ищет следующий? Это так работает?

Предполагалось, что следующий сценарий будет воспроизводить проблему, но на той же машине он работает безупречно:

$repoRoot = "C:\Temp\HgDeleteTest\MyRepo"
remove-item $repoRoot -recurse -force
md $repoRoot
pushd $repoRoot
hg.exe init
add-content ShouldBeLeftBehind.txt "This is some text in a file that should be left behind once the various .hg files/directories are removed."
add-content .hgignore syntax:glob
add-content .hgignore *.dll
add-content .hgignore *.exe
hg.exe commit --addremove --message "Building test repository with one commit."
gci -rec -filter ".hg*" | remove-item -recurse -force
popd

Ответы [ 4 ]

1 голос
/ 20 июля 2011

Я закончил тем, что отделил поиск от удаления. Я полагаю, что моя проблема заключалась в том, как по умолчанию работает трубопровод (то есть по одному элементу за раз), но я не смог создать тест для его проверки.

В любом случае, отлично работает следующее:

$hgObjects = gci -rec | ?{ $_.name -like ".hg*" -and $_.name -ne ".hgignore" }
remove-item $hgObjects -force -recurse

Используя этот стиль, командлет remove-item получает массив найденных элементов и обрабатывает их.

Папка .hg в моем исходном примере не содержала ничего под названием .hg*, поэтому я не вижу, что происходит. Мне казалось, что он пытался удалить папку дважды, что я нахожу очень странным. Интересно, является ли это PowerShell проявлением этого стандартного поведения .NET:

Перечислитель остается действительным, пока остается коллекция без изменений. Если в коллекцию внесены изменения, такие как добавление, изменяя или удаляя элементы, перечислитель может быть аннулирован и следующий вызов MoveNext или Reset может бросить InvalidOperationException. Если коллекция изменена между MoveNext и Current, Current возвращает элемент, для которого он установлен, даже если перечислитель уже признан недействительным. (Взято из http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator(v=vs.71).aspx).

1 голос
/ 20 июля 2011

Следующее будет ограничивать удаление только файлами и исключать папки.

gci -rec -filter ".hg*" | Where {$_.psIsContainer -eq $false} | remove-item -recurse -force

Затем запустите его снова, удалив папки:

gci -rec -filter ".hg*" | Where {$_.psIsContainer -eq $true} | remove-item -recurse -force
1 голос
/ 20 июля 2011

Может быть, вы удаляете папку, начинающуюся с .hg, которая, в свою очередь, содержит файл, начинающийся с .hg, но этот файл больше не существует?

0 голосов
/ 20 июля 2011

Я полагаю, что Антоний прав: использование -recurse в gci перечислит и файлы, и каталоги, соответствующие ".hg *".Каталог будет возвращен первым.Затем remove-item сначала удаляет каталог, а ключ -force удаляет все файлы в нем.Затем он пытается удалить файлы, находящиеся в этом каталоге, которые соответствуют «.hg *» (которые были там, когда запускался gci), но теперь их нет.Это должно остановить ошибки:

gci ".hg*" -recurse | select -expand fullname | sort length -desc | remove-item -force

Сортировка полных имен в порядке убывания длины гарантирует, что ни один сопоставленный родительский каталог не будет удален до того, как будут удалены все сопоставленные файлы в этом каталоге.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...