Я пытаюсь рекурсивно удалить каталог с помощью rm -Force -Recurse somedirectory
, Я получаю несколько ошибок «Каталог не пустой». Если я повторите ту же команду, это удается.
Пример:
PS I:\Documents and Settings\m\My Documents\prg\net> rm -Force -Recurse .\FileHelpers
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests\Data\RunTime\_svn: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (_svn:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests\Data\RunTime: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (RunTime:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests\Data: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (Data:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (FileHelpers.Tests:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\Libs\nunit\_svn: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (_svn:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\Libs\nunit: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (nunit:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\Libs: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (Libs:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers: The directory is not empty.
At line:1 char:3
+ rm <<<< -Force -Recurse .\FileHelpers
+ CategoryInfo : WriteError: (I:\Documents an...net\FileHelpers:DirectoryInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
PS I:\Documents and Settings\m\My Documents\prg\net> rm -Force -Recurse .\FileHelpers
PS I:\Documents and Settings\m\My Documents\prg\net>
Конечно этого не бывает всегда. Кроме того, это не происходит только с _svn
каталоги, а у меня нет TortoiseSVN cache или что-то в этом роде, поэтому каталог не блокируется.
Любые идеи?
help Remove-Item
говорит:
Параметр Recurse в этом командлете не работает должным образом.
и
Поскольку параметр Recurse в этом командлете неисправен, команда использует командлет Get-Childitem для получения желаемых файлов d и использует оператор конвейера для передачи их в командлет Remove-Item.
и предлагает эту альтернативу в качестве примера:
get-childitem * -include *.csv -recurse | remove-item
Итак, вы должны трубить get-childitem -recurse
в remove-item
.
@JamesCW: проблема все еще существует в PowerShell 4.0
Я попробовал другой обходной путь, и он сработал: используйте cmd.exe:
&cmd.exe /c rd /s /q $somedirectory
ETA 20181217: PSVersion 4.0 и более поздние версии по-прежнему не работают при некоторых обстоятельствах, см. Альтернативный ответ от Мехрдад Мирреза, и отчет об ошибке поданный мклемент
мклемент предоставляет решение Proof of Concept на этом ТАК ответ, поскольку ошибка ожидает официального исправления
Новая версия PowerShell
(PSVersion 4.0
) полностью решил эту проблему и Remove-Item "targetdirectory" -Recurse -Force
работает без проблем с синхронизацией.
Вы можете проверить свою версию, запустив $PSVersiontable
изнутри ISE или PowerShell
Подсказка. 4.0 - это версия, которая поставляется с Windows 8.1
и Server 2012 R2
, и его также можно установить в предыдущих версиях Windows.
Обновить: Вроде бы есть планы чтобы сделать API удаления элементов файловой системы Windows синхронными, но они еще не синхронизированы в Windows 10 версии 1903 - см. этот комментарий на GitHub.
Существующие ответы смягчать проблема, поэтому она возникает реже, но они не решают основная причина, поэтому сбои все еще могут происходить.
Remove-Item -Recurse
неожиданно асинхронный, в конечном итоге потому, что Методы Windows API для удаления файлов и каталогов по своей сути асинхронны. и Remove-Item
не учитывает это.
это периодически, непредсказуемо проявляется одним из двух способов:
Ваш случай: удаление самого непустого каталога может завершиться ошибкой, если удаление подкаталога или файла в нем еще не завершено к моменту попытки удалить родительский каталог.
Реже: воссоздание удаленного каталога сразу после удаления может завершиться ошибкой, поскольку удаление могло еще не завершиться к моменту попытки повторного создания.
В проблема затрагивает не только PowerShell Remove-Item
, но также cmd.exe
с rd /s
а также .NET [System.IO.Directory]::Delete()
:
Начиная с Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1 / cmd.exe
10.0.17134.407 / .NET Framework 4.7.03056, .NET Core 2.1, ни то, ни другое Remove-Item
, ни rd /s
, ни [System.IO.Directory]::Delete()
работать надежно, потому что они не учитывать асинхронное поведение функций удаления файлов / каталогов Windows API:
Для настраиваемая функция PowerShell что обеспечивает надежно синхронный обходной путь, видеть этот ТАК ответ.
Текущий ответ на самом деле не удаляет каталог, а только его дочерние элементы. Кроме того, у него будут проблемы с вложенными каталогами, так как он снова будет пытаться удалить каталог до его содержимого. Я написал что-то, чтобы удалить файлы в правильном порядке, все равно будет та же проблема, хотя иногда каталог все еще будет после этого.
Итак, теперь я использую что-то, что будет ловить исключение, ждать и повторять (3 раза):
На данный момент я использую это:
function EmptyDirectory($directory = $(throw "Required parameter missing")) {
if ((test-path $directory) -and -not (gi $directory | ? { $_.PSIsContainer })) {
throw ("EmptyDirectory called on non-directory.");
}
$finished = $false;
$attemptsLeft = 3;
do {
if (test-path $directory) {
rm $directory -recurse -force
}
try {
$null = mkdir $directory
$finished = $true
}
catch [System.IO.IOException] {
Start-Sleep -Milliseconds 500
}
$attemptsLeft = $attemptsLeft - 1;
}
while (-not $finished -and $attemptsLeft -gt 0)
if (-not $finished) {
throw ("Unable to clean and recreate directory " + $directory)
}
}
Чтобы удалить каталог и его содержимое, нужно выполнить два шага. Сначала удалите содержимое, затем саму папку. Используя обходной путь для ошибочного рекурсивного элемента удаления, решение будет выглядеть следующим образом:
Get-ChildItem -Path "$folder\\*" -Recurse | Remove-Item -Force -Recurse
Remove-Item $folder
Таким образом, вы также можете удалить родительский каталог.
Гоша. Множество ответов. Я честно предпочитаю этот всем им. Он очень простой, полный, читаемый и работает на любом компьютере с Windows. Он использует (надежную) функцию рекурсивного удаления .NET, и если по какой-то причине он не работает, он генерирует правильное исключение, которое можно обработать с помощью блока try / catch.
$fullPath = (Resolve-Path "directory\to\remove").ProviderPath
[IO.Directory]::Delete($fullPath, $true)
Обратите внимание, что Resolve-Path
Строка важна, потому что .NET не знает ваш текущий каталог при разрешении относительных путей к файлам. Это единственное, что я могу придумать.
Вот что у меня работает:
$Target = "c:\folder_to_delete"
Get-ChildItem -Path $Target -Recurse -force |
Where-Object { -not ($_.psiscontainer) } |
Remove-Item –Force
Remove-Item -Recurse -Force $Target
Эта первая строка удаляет все файлы в дереве. Второй удаляет все папки, включая верхнюю.
Сначала возьмите на себя ответственность за файлы / каталоги, используя Takeown.exe, затем удалите
https://learn-powershell.net/2014/06/24/changing-ownership-of-file-or-folder-using-powershell/
У меня была проблема с каталогом, который нельзя было удалить. Я обнаружил, что одна из вложенных папок была повреждена, и когда я попытался переместить или переименовать этот дочерний каталог, я получил сообщение об ошибке, в котором говорилось о его отсутствии. Я попытался использовать rm -Force и получил ту же ошибку, что и вы.
У меня сработало сжатие родительского каталога с помощью 7-zip с установленной опцией «Удалить файлы после сжатия». После сжатия я смог удалить zip-файл.