PowerShell'de zorla kaldırılan dosyalar ve dizinler bazen başarısız oluyor, ancak her zaman değil


33

Bir dizini yinelemeli olarak silmeye çalışıyorum rm -Force -Recurse somedirectory, birkaç "Dizin boş değil" hatası alıyorum. Ben ise aynı komutu yeniden denemek , başarılı.

Örnek:

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>

Tabii ki, bu her zaman olmaz . Ayrıca, yalnızca _svndizinlerde gerçekleşmez ve bir TortoiseSVN önbelleğim veya buna benzer bir şeyim yok, bu nedenle hiçbir şey dizini engellemiyor.

Herhangi bir fikir?

Yanıtlar:


31

help Remove-Item diyor:

Bu cmdlet'teki Recurse parametresi düzgün çalışmıyor.

ve

Bu cmdlet'teki Recurse parametresi arızalı olduğundan, komut, arzu d dosyalarını almak için Get-Childitem cmdlet'ini kullanır ve bunları, bunları Kaldır-Öğesi cmdlet'ine iletmek için boru hattı operatörünü kullanır.

ve bu alternatifi örnek olarak önermektedir:

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

Bu yüzden get-childitem -recurseiçine boru gerekir remove-item.


Teşekkürler. 2006'dan bu konuyu yeni buldum: vistax64.com/powershell/… Microsoft'un bunu düzeltmekle gerçekten ilgilenmediğini gösteriyor.
Mauricio Scheffer

@mausch: Bunu daha yeni, ancak hala çözülmemiş olarak görün, referans: Remove-Item -Recurse
sonraki bildirime kadar duraklatıldı.

bir gezinme yapar ve silerseniz, önce alt dizinleri ve önce bu dosyaları taramanız gerekir.
fschwiet

2
En azından belgeler işe yaramadığını söylüyor.
derekerdmann 20:11

6
Her iki -force -recurse işaretini Remove-Item için koymak zorunda kaldım, aksi halde "lütfen onayla" diye sormamı sağla-Get-ChildItem -Path $ Hedef -Recurse | Kaldırma Öğesi
-force -recurse

17

@JamesCW: Sorun PowerShell 4.0'da hala var

Başka bir geçici çözüm denedim ve işe yaradı: cmd.exe kullanın:

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

1
İyi eski rd / s / q!
JamesCW

Get-ChildItem'in her varyasyonunu denedim; yeniden deneme döngüleri; çağırarak iisresetsilme ve hiçbir şey eskisi iş gibi görünüyor güvenilir . Bunu deneyeceğim, ilk gördüğümde Powershell'imin içinde DOS'a sahip olduğum için ballanmışım ...
Peter McEvoy

Ne yazık ki, rd /saralıklı olarak da başarısız oluyor (görünüşe göre daha az sıklıkta olsa da Remove-Item): github.com/Microsoft/console/issues/309
mklement

Benim için c tarafından kesikli gibi değil. Bundan önce powershell-komutundan ve cmd.exe bölümünden alıntı yapmanız gerekecek mi? "/" İşlecini izleyen bir değer ifadesi sağlamalısınız. " "Beklenmeyen simge 'c' ifadesinde veya ifadesinde. Bu, önünde powershell-komutuyla aynıdır. / Kaçmayı gerektirir mi?
Michele,

7

ETA 20181217: PSVersion 4.0 ve sonrası bazı durumlarda hala başarısız olacak, Mehrdad Mirreza'nın alternatif cevabına ve mklement tarafından dosyalanan hata raporuna bakınız.

Hata resmi bir düzeltmeyi beklediğinden, mklement bu SO cevabında bir Kanıt Kanıtı çözümü sunar

PowerShell( PSVersion 4.0) Adlı yeni sürüm bu sorunu tamamen çözdü ve Remove-Item "targetdirectory" -Recurse -Forcezamanlama problemi olmadan çalışıyor.

Sürümünüzü $PSVersiontableİMKB veya bilgi PowerShellistemi içinden çalıştırarak kontrol edebilirsiniz . 4.0, ve ile birlikte gelen sürümdür Windows 8.1ve Server 2012 R2Windows'un önceki sürümlerinde de yüklenebilir.


5
PowerShell 4.0'da hala benim için ortaya çıkıyor
ajbeaven

10
Hala PowerShell v5'te gerçekleşir !!!!! 11 !! 1! 1 !!!
Richard Hauer

@RichardHauer iyi şimdi kafam karıştı
JamesCW

2
@JamesCW Sürüme dönüştürdüm rd. Çalışmanın dışında, yaklaşık 3 kat daha hızlı
Richard Hauer

Sorun olan değil bakın - Windows PowerShell v5.1 / PowerShell Çekirdek 6.2.0-preview.1 olarak düzeltildi bu hata raporu . Daha rd /saz sıklıkta başarısız olsa da, bozulur - bu hata raporuna bakın .
mklement

4

Güncelleştirme : Görünüşe göre Windows dosya sistemi öğe kaldırma API'lerini senkronize etme planları var , ancak henüz Windows 10 sürüm 1903'ten itibaren senkronize değiller - GitHub'da bu yorumu inceleyin .


Mevcut cevaplar problemi azaltıyor , böylece daha az sıklıkta ortaya çıkıyor, ancak temel nedene değinmiyorlar , bu yüzden başarısızlıklar hala devam ediyor.

Remove-Item -Recurseçünkü beklenmedik şekilde eşzamansız , çünkü sonuçta Windows API yöntemleri, dosya ve dizinlerin kaldırılması için içsel olarak eşzamansız ve Remove-Itembunu hesaba katmıyor .

Bu zaman zaman, tahmin edilemez biçimde iki yoldan biriyle kendini gösterir:

  • Sizin durumunuz: Bir alt dizinin veya dosyanın kaldırılması, henüz ana dizini kaldırmak için bir girişimde bulunulduğunda tamamlanmadıysa, boş olmayan bir dizinin kaldırılması başarısız olabilir.

  • Daha az yaygın: Kaldırma işleminden hemen sonra kaldırılmış bir dizinin yeniden oluşturulması başarısız olabilir, çünkü kaldırma işlemi, yeniden oluşturma girişimi sırasında henüz tamamlanmamış olabilir.

Sorun sadece PowerShell en etkilemektedir Remove-Item, ama aynı zamanda cmd.exes' rd /sNET en yanı sıra[System.IO.Directory]::Delete() :

/ PowerShell Çekirdek 6.2.0-preview.1 / Windows PowerShell v5.1 itibariyle cmd.exe10.0.17134.407 / .NET Framework 4.7.03056, .NET Çekirdek 2.1, ne Remove-Item, ne rd /s, ne [System.IO.Directory]::Delete()güvenilir bir iş onlar çünkü, asenkron hesaba başarısız Windows API dosyası / dizin kaldırma işlevlerinin davranışı :

Bir İçin Özel PowerShell fonksiyonu bir sağlar güvenilir senkron geçici çözümü görmek bu SO cevabı .


Kaldırma işleminin kesin olduğu dosyaları işlerken:while($true) { if ( (Remove-Item [...] *>&1) -ne $null) { Start-Sleep 0.5 } else { break } }
Farway

3

Mevcut cevap aslında bir dizini, sadece alt dosyalarını silmez. Dahası, içindekiler diziniyle ilgili problemleri olacaktır çünkü içeriğinden önce bir dizini silmeye çalışacaktır. Dosyaları doğru sırayla silmek için bir şeyler yazdım, yine de bazen dizin yine de buralarda olacak olsa da hala aynı sorunu yaşardım.

Şimdi, istisnayı yakalayacak, bekleyip tekrar deneyecek bir şey kullanıyorum (3 kez):

Şimdilik bunu kullanıyorum:

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
Bu iyi ama hala problemlerim vardı. Mkdir komutu sistem rm komutunu tamamlamadan önce çalışırsa, bir System.UnauthorizedAccessException öğesini, ItemExistsUnauthorizedAccessError öğesinin FullyQualifiedErrorId öğesiyle birlikte atabilir. Yani, dizin henüz işletim sistemi tarafından silinmedi (yavaş HDD'mde). Bu yüzden bu hatanın da yakalanması gerekiyor. Ve bu bitmeyen bir hatadır, bu yüzden ErrorAction'ın Dur olarak ayarlanması gerekir. Ayrıca rm komutunu da try bloğuna koydum, sadece silerken geçici IO hataları olması durumunda.
Mark Lapierre

Bunun yapılması gerektiğine bile inanamıyorum. Kahretsin, Powershell berbat!
jcollum

3

Dizini ve içeriğini silmek iki adım alır. Önce içeriği, sonra klasörün kendisini silin. Arızalı özyinelemeli kaldır öğe için geçici çözüm kullanarak çözüm şöyle görünür

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

Bu şekilde ana dizini de kaldırabilirsiniz.


1
Bu kesinlikle kabul edilen cevabın söylediği şey. Ekleyeceğin bir şey var mı?
Michael Hampton

1
Kabul edilen cevabın dizinin kendisini silmediğine işaret ediyorlar, bu yüzden iki adım atıyor.
Paul George

2
Remove-ItemBaşlangıçta belirtilen aynı sorun var içine boru komuta. Aynı şekilde boş olmayan bir dizin öğesinde yanabilir.
Dejan

@Dejan Bu kodun ilk satırı işe yaradıysa bu dizin boş olamazdı, değil mi?
Ifedi Okonkwo

1
Bu olsa azaltmak başarısızlık ihtimalini, hala göz önüne alındığında, başarısız olabilir Remove-Item -Recursehala ilgilenmektedir. Temel sorun hala Windows PowerShell v5.1 / PowerShell Çekirdek 6.2.0-önizleme.1'den itibaren mevcut - bu hata raporuna bakın .
mklement

3

Allah Allah. Bir sürü cevap. Dürüstçe bunu hepsinden tercih ederim. Süper basit, eksiksiz, okunabilir ve herhangi bir Windows makinesinde çalışır. .NET'in (güvenilir) özyinelemeli silme işlevini kullanır ve bir nedenden dolayı başarısız olursa, bir try / catch bloğu ile işlenebilecek uygun bir istisna atar.

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

Resolve-PathGöreceli dosya yollarını çözerken .NET'in geçerli dizininizden haberdar olmadığından satırın önemli olduğunu unutmayın . Bu düşünebildiğim tek şey hakkında.


2

Bu benim çalışmam gereken şey:

$Target = "c:\folder_to_delete"

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

Remove-Item -Recurse -Force $Target

Bu ilk satır, ağaçtaki tüm dosyaları siler. İkincisi, üst kısmı da dahil olmak üzere tüm klasörleri siler.


Bu olsa azaltmak başarısızlık ihtimalini, hala göz önüne alındığında, başarısız olabilir Remove-Item -Recursehala ilgilenmektedir. Temel sorun hala Windows PowerShell v5.1 / PowerShell Çekirdek 6.2.0-önizleme.1'den itibaren mevcut - bu hata raporuna bakın .
mklement


0

Bu sorunu silmeyecek bir dizinde yaşadım. Alt klasörlerden birinin bozuk olduğunu ve o alt dizini taşımaya veya yeniden adlandırmaya çalıştığımda, eksik olduğunu söyleyen bir hata mesajı alıyorum. Rm -Force'u kullanmayı denedim ve yaptığınız hatayı aldım.

Benim için ne işe yaradı "sıkıştırma sonra dosyaları Sil" seçeneği işaretli 7-zip kullanarak ebeveyn dir sıkıştırıyordu. Sıkıştırıldığında, zip dosyasını silebildim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.