Os arquivos e diretórios de remoção de força no PowerShell falham às vezes, mas nem sempre

28

Eu estou tentando excluir um diretório recursivamente com rm -Force -Recurse somedirectory , recebo vários erros "O diretório não está vazio". Se eu repetir o mesmo comando , será bem sucedido.

Exemplo:

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>

Claro, isso não acontece sempre . Além disso, isso não acontece apenas com _svn diretórios, e eu não tenho um cache TortoiseSVN ou algo parecido que nada está bloqueando o diretório.

Alguma idéia?

    
por Mauricio Scheffer 09.11.2010 / 16:42

8 respostas

29

help Remove-Item diz:

The Recurse parameter in this cmdlet does not work properly.

e

Because the Recurse parameter in this cmdlet is faulty, the command uses the Get-Childitem cmdlet to get the desire d files, and it uses the pipeline operator to pass them to the Remove-Item cmdlet.

e propõe esta alternativa como exemplo:

get-childitem * -include *.csv -recurse | remove-item

Então você deve canalizar get-childitem -recurse em remove-item .

    
por 09.11.2010 / 19:35
15

@JamesCW: O problema ainda existe no PowerShell 4.0

Eu tentei outra solução alternativa e funcionou: use cmd.exe:

&cmd.exe /c rd /s /q $somedirectory
    
por 10.09.2015 / 08:59
6

A nova versão de PowerShell ( PSVersion 4.0 ) resolveu esse problema completamente e o Remove-Item "targetdirectory" -Recurse -Force funciona sem nenhum problema de tempo.

Você pode verificar sua versão executando $PSVersiontable no prompt ISE ou PowerShell . 4.0 é a versão que vem com Windows 8.1 e Server 2012 R2 e também pode ser instalada em versões anteriores do Windows.

    
por 27.05.2015 / 17:36
3

A resposta atual não irá realmente excluir um diretório, apenas seus filhos. Além disso, ele terá problemas com diretórios aninhados, pois ele tentará novamente excluir um diretório antes de seu conteúdo. Eu escrevi algo para excluir os arquivos na ordem correta, ainda teria o mesmo problema, embora às vezes o diretório ainda estaria por aí depois.

Então, agora eu uso algo que captura a exceção, aguarda e repete (3 vezes):

Por enquanto estou usando isso:

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)
    }
}
    
por 26.12.2010 / 23:36
3

Para excluir o diretório e seu conteúdo, execute duas etapas. Primeiro, apague o conteúdo e depois a própria pasta. Usando a solução alternativa para o item de remoção recursivo com falha, a solução ficaria assim:

Get-ChildItem -Path "$folder\*" -Recurse | Remove-Item -Force -Recurse
Remove-Item $folder

Dessa forma, você também pode remover o diretório pai.

    
por 14.12.2013 / 00:40
2

Isso é o que tenho trabalhado:

$Target = "c:\folder_to_delete"

Get-ChildItem -Path $Target -Recurse -force |
  Where-Object { -not ($_.psiscontainer) } |
   Remove-Item –Force

Remove-Item -Recurse -Force $Target

Esta primeira linha exclui todos os arquivos da árvore. O segundo exclui todas as pastas, incluindo o topo.

    
por 30.09.2015 / 23:20
1

As respostas existentes mitigam o problema, de modo que ocorra com menos frequência, mas não abordam a causa raiz , razão pela qual as falhas ainda podem ocorrer.

Remove-Item -Recurse é inesperadamente assíncrono , em última análise, porque os métodos API do Windows para remoção de arquivos e diretórios são inerentemente assíncronos e Remove-Item não não conta para isso.

Isso intermitentemente, imprevisivelmente se manifesta de duas maneiras:

  • Seu caso: A remoção de um diretório não vazio pode falhar, caso a remoção de um subdiretório ou arquivo ainda não tenha sido concluída até que seja feita uma tentativa de remover o diretório pai.

  • Menos comumente: a recriação de um diretório removido imediatamente após a remoção pode falhar, porque a remoção pode ainda não ter sido concluída quando a recriação for tentada.

O problema afeta não apenas o Remove-Item do PowerShell, mas também o cmd.exe do rd /s , além do [System.IO.Directory]::Delete() do .NET:

A partir do Windows PowerShell v5.1 / Pré-visualização do PowerShell Core 6.2.0.1 / cmd.exe 10.0.17134.407 / .NET Framework 4.7.03056, .NET Core 2.1, nenhum Remove-Item , nem rd /s , nem [System.IO.Directory]::Delete() funcionam de forma confiável , porque eles não levam em consideração o comportamento assíncrono das funções de remoção de diretório / arquivo da API do Windows :

Para uma função personalizada do PowerShell que fornece uma solução síncrona confiável , consulte esta resposta SO .

    
por 01.12.2018 / 15:25
0

Assuma a propriedade dos arquivos / diretórios usando primeiro o Takeown.exe e exclua

link

    
por 17.08.2016 / 19:18