PowerShell의 파일 및 디렉토리 강제 제거가 때때로 실패하지만 항상 그런 것은 아닙니다.


33

과 함께 디렉토리를 반복적으로 삭제하려고하는데 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 캐시 또는 이와 유사한 것이 없으므로 디렉토리를 차단하는 것이 없습니다.

어떤 아이디어?

답변:


31

help Remove-Item 말한다 :

이 cmdlet의 Recurse 매개 변수가 제대로 작동하지 않습니다.

과

이 cmdlet의 Recurse 매개 변수에 결함이 있으므로 명령은 Get-Childitem cmdlet을 사용하여 원하는 d 파일을 가져오고 파이프 라인 연산자를 사용하여 해당 파일을 Remove-Item cmdlet에 전달합니다.

이 대안을 예로 제안합니다.

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

당신이 파이프를해야 그래서 get-childitem -recurse속으로 remove-item.


감사. vistax64.com/powershell/… 2006 년 부터이 스레드를 찾았습니다. Microsoft가 실제로이 문제를 수정하는 데 관심이없는 것 같습니다.
— Mauricio Scheffer 2

@mausch :보다 최근에 확인되었지만 여전히 해결되지 않은 참조를 참조하십시오. Remove-Item -Recurse
— 추가 통지가있을 때까지 일시 중지되었습니다.

순회 및 삭제를 수행하는 경우 하위 디렉토리를 먼저 순회하고 파일을 먼저 순회해야합니다.
— fschwiet

2
적어도 문서에는 작동하지 않는다고 나와 있습니다.
— derekerdmann

6
Remove-Item에 대해 -force -recurse 플래그를 모두 넣어야했습니다. 그렇지 않으면 "확인하십시오"라는 메시지가 계속 나타납니다. Get-ChildItem -Path $ Destination -Recurse | Remove-Item -force -recurse
— MiFreidgeim SO 중지 그만

17

@JamesCW : 문제는 여전히 PowerShell 4.0에 있습니다.

다른 해결 방법을 시도하고 작동했습니다 .cmd.exe를 사용하십시오.

&cmd.exe /c rd /s /q $somedirectory

1
좋은 rd / s / q!
— JamesCW

Get-ChildItem의 모든 변형을 시도했습니다. 재시도 루프; 호출 iisreset삭제하지 아무것도하기 전에하는 것은 작동하는 것 같다 안정적 . 처음 보았을 때 Powershell 내부에 DOS를 설치하는 데 어려움을 겪었지만이 방법을 시도 할 것입니다.
— Peter McEvoy

불행하게도, rd /s(비록 겉으로는 적게 비해 너무 간헐적으로 실패 Remove-Item) : github.com/Microsoft/console/issues/309
— mklement

그것은 나를 위해 c에 의한 슬래시를 좋아하지 않습니다. powershell -command와 cmd.exe 부분을 작은 따옴표로 묶어야합니까? " '/'연산자 다음에 값 표현식을 제공해야합니다." "표현식이나 진술에서 예상치 못한 토큰 'c'. 앞의 powershell 명령과 동일합니다. / 탈출해야합니까?
— Michele

7

ETA 20181217 : PSVersion 4.0 이상은 일부 상황에서 여전히 실패합니다. Mehrdad Mirreza의 대체 답변 참조 및 mklement가 제출 한 버그 보고서

버그가 공식 수정을 기다리고 있기 때문에 mklement 는이 SO 답변 에서 개념 증명 솔루션을 제공합니다.

PowerShell( PSVersion 4.0) 의 새 버전은 이 문제를 완전히 해결했으며 Remove-Item "targetdirectory" -Recurse -Force타이밍 문제없이 작동합니다.

$PSVersiontableISE 또는 PowerShell프롬프트 내에서 실행하여 버전을 확인할 수 있습니다 . 4.0 버전이 함께 제공 Windows 8.1하고 Server 2012 R2, 그리고 그것은뿐만 아니라 이전 버전의 Windows에 설치할 수 있습니다.


5
PowerShell 4.0에서도 여전히 발생
— ajbeaven

10
PowerShell v5에서도 여전히 발생합니다 !!!!! 11 !! 1! 1 !!!
— Richard Hauer

@RichardHauer 잘 지금은 혼란스러워
— JamesCW

2
@JamesCW rd버전으로 변환했습니다 . 을 제외하고 실제로 작동, 더 빨리 배에 관하여
— 리처드 하우어

Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1부터이 문제가 해결 되지 않았습니다 . 이 버그 보고서를 참조하십시오 . rd /s자주 실패 하지는 않지만 고장이 발생 합니다. 이 버그 보고서를 참조하십시오 .
— mklement

4

업데이트 : Windows 파일 시스템 항목 제거 API를 동기식으로 만들 계획 이 있지만 Windows 10 버전 1903부터 아직 동기식이 아닙니다 . GitHub에 대한 이 의견을 참조하십시오 .


기존 답변 은 문제를 완화 하여 문제가 덜 발생하지만 근본 원인을 해결하지 못하므로 오류가 계속 발생할 수 있습니다.

Remove-Item -Recurse파일 및 디렉토리 제거를위한 Windows API 메소드는 본질적으로 비동기식 이며이를 설명 Remove-Item하지 않기 때문에 예기치 않게 비동기식 입니다.

이것은 간헐적으로 예측할 수없는 두 가지 방법 중 하나로 나타납니다.

  • 귀하의 경우 : 상위 디렉토리를 제거하려고 시도 할 때까지 하위 디렉토리 또는 파일의 디렉토리 제거가 아직 완료되지 않은 경우 비어 있지 않은 디렉토리 자체를 제거하지 못할 수 있습니다.

  • 덜 일반적 : 재 작성을 시도 할 때까지 제거가 아직 완료되지 않았기 때문에 제거 직후에 제거 된 디렉토리를 다시 작성하는 데 실패 할 수 있습니다.

문제는 PowerShell에서의 영향을하지 Remove-Item뿐만 아니라 cmd.exe이야 ' rd /s.NET의뿐만 아니라[System.IO.Directory]::Delete() :

/ PowerShell을 핵심 6.2.0-preview.1 /의 Windows PowerShell 버전 5.1의로 cmd.exe10.0.17134.407 / .NET 프레임 워크 4.7.03056, .NET 코어 2.1 도 Remove-Item,도 rd /s,도 [System.IO.Directory]::Delete()안정적으로 작동 그들이 있기 때문에, 비동기에 대한 계정에 실패 Windows API 파일 / 디렉토리 제거 기능의 동작 :

안정적인 동기 해결 방법 을 제공 하는 사용자 지정 PowerShell 기능 에 대해서는 이 SO 답변을 참조하십시오 .


제거가 확실한 파일을 처리 할 때 :while($true) { if ( (Remove-Item [...] *>&1) -ne $null) { Start-Sleep 0.5 } else { break } }
— Farway

3

현재 답변은 실제로 디렉토리를 삭제하지 않으며 하위 디렉토리 만 삭제합니다. 또한 내용보다 먼저 디렉토리를 삭제하려고 시도하므로 중첩 디렉토리에 문제가 있습니다. 올바른 순서로 파일을 삭제하기 위해 무언가를 썼지 만 때로는 디렉토리가 여전히 뒤에있을지라도 여전히 같은 문제가 있습니다.

이제 예외를 포착하고 기다렸다가 다시 시도하는 것을 사용합니다 (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)
    }
}

1
이것은 좋지만 여전히 문제가 있습니다. 시스템이 rm 명령을 완료하기 전에 mkdir 명령이 실행되면 ItemExistsUnauthorizedAccessError의 FullyQualifiedErrorId와 함께 System.UnauthorizedAccessException이 발생할 수 있습니다. 즉, 디렉토리가 아직 느린 HDD에서 OS에 의해 삭제되지 않았습니다. 따라서 오류도 잡아야합니다. 그리고 종료되지 않은 오류이므로 ErrorAction을 Stop으로 설정해야합니다. 삭제시 일시적인 IO 오류가있는 경우를 대비하여 rm 명령을 try 블록에도 넣습니다.
— Mark Lapierre

나는 이것이 완료되어야한다고 믿을 수 없다. 젠장, Powershell이 ​​짜증 난다!
— jcollum

3

디렉토리와 그 내용을 삭제하려면 두 단계가 필요합니다. 먼저 내용을 삭제 한 다음 폴더 자체를 삭제하십시오. 잘못된 재귀 제거 항목에 대한 해결 방법을 사용하면 솔루션은 다음과 같습니다.

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

이 방법으로 상위 디렉토리도 제거 할 수 있습니다.


1
이것이 바로 받아 들여진 대답입니다. 추가 할 것이 있습니까?
— Michael Hampton

1
그들은 받아 들인 대답이 디렉토리 자체를 삭제하지 않으므로 두 단계를 수행한다고 지적합니다.
— 폴 조지

2
는 Remove-Item원래 명시된 것과 같은 문제가로 배관을 명령. 같은 방법으로 비어 있지 않은 디렉토리 항목에서 우연히 발견 될 수 있습니다.
— Dejan

@Dejan이 코드의 첫 줄이 작동하면이 디렉토리를 비울 수 없었습니까?
— Ifedi Okonkwo 2016 년

1
이는 실패 가능성을 감소시킬 수 있지만 Remove-Item -Recurse여전히 관련되어 있다고 해도 실패 할 수 있습니다 . 기본 문제는 여전히 Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1부터 존재합니다 . 이 버그 보고서를 참조하십시오 .
— mklement

3

어이. 많은 답변. 나는 솔직히이 모든 것을 선호합니다. 매우 간단하고 완벽하며 읽을 수 있으며 모든 Windows 시스템에서 작동합니다. .NET의 (신뢰할 수있는) 재귀 삭제 기능을 사용하며 어떤 이유로 실패하면 try / catch 블록으로 처리 할 수있는 적절한 예외가 발생합니다.

$fullPath = (Resolve-Path "directory\to\remove").ProviderPath
[IO.Directory]::Delete($fullPath, $true)

합니다 Resolve-Path상대 파일 경로를 해석 할 때 .NET은 현재 디렉토리를 인식하지 않기 때문에 라인이 중요하다. 그것은 내가 생각할 수있는 유일한 문제입니다.


2

이것이 내가 일한 것입니다.

$Target = "c:\folder_to_delete"

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

Remove-Item -Recurse -Force $Target

이 첫 번째 줄은 트리의 모든 파일을 삭제합니다. 두 번째는 상단을 포함하여 모든 폴더를 삭제합니다.


이는 실패 가능성을 감소시킬 수 있지만 Remove-Item -Recurse여전히 관련되어 있다고 해도 실패 할 수 있습니다 . 기본 문제는 여전히 Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1부터 존재합니다 . 이 버그 보고서를 참조하십시오 .
— mklement


0

삭제되지 않는 디렉토리 에이 문제가있었습니다. 하위 폴더 중 하나가 손상되어 해당 하위 디렉토리를 이동하거나 이름을 바꾸려고 할 때 누락 된 내용에 대한 오류 메시지가 나타납니다. rm -Force를 사용하려고 시도했지만 동일한 오류가 발생했습니다.

나를 위해 일한 것은 "압축 후 파일 삭제"옵션을 선택한 상태에서 7-zip을 사용하여 부모 디렉토리를 압축하는 것이 었습니다. 압축되면 zip 파일을 삭제할 수있었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.