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 का उपयोग इच्छा डी फ़ाइलों को प्राप्त करने के लिए करता है, और यह पाइपलाइन ऑपरेटर का उपयोग उन्हें हटाने-आइटम cmdlet में पारित करने के लिए करता है।

और इस विकल्प को एक उदाहरण के रूप में प्रस्तावित करता है:

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

तो तुम पाइप चाहिए get-childitem -recurseमें remove-item


धन्यवाद। बस 2006 से यह धागा मिला: vistax64.com/powershell/… ऐसा लगता है कि Microsoft वास्तव में इसे ठीक करने में दिलचस्पी नहीं रखता है।
मौरिसियो शेफ़र

@mausch: इसे और हाल ही में देखें, लेकिन अभी भी अनसुलझे हैं, संदर्भ: निकालें-आइटम -Recurse
आगे की सूचना तक

यदि आप एक ट्रैवर्सल और डिलीट करते हैं, तो आपको पहले चाइल्ड डायरेक्टरीज़, और उनकी फाइल्स को पहले से ट्रेस करना होगा।
fschwiet

2
कम से कम प्रलेखन का कहना है कि यह काम नहीं करता है।
derekerdmann

6
मुझे Remove-Item के लिए दोनों -force -recurse झंडे लगाने थे, अन्यथा यह मुझे संकेत देता रहा "कृपया पुष्टि करें" Get-ChildItem -Path $ Destination -Recurse | Remove-Item -force -recurse
MiFreidgeim SO-stop बुराई

17

@JamesCW: समस्या अभी भी PowerShell 4.0 में मौजूद है

मैंने एक और समाधान की कोशिश की और यह काम किया: cmd.exe का उपयोग करें:

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

1
अच्छा पुराना rd / s / q!
जेम्सकॉब

मैंने गेट-चाइल्ड इटेम के हर बदलाव की कोशिश की है; पुनः प्रयास करें; iisresetहटाने से पहले कॉल करना और मज़बूती से काम करना प्रतीत नहीं होता है । मैं यह कोशिश करने वाला हूं, हालांकि जब मैंने पहली बार यह देखा था तो मैंने अपने पॉवर्सशेल के अंदर डॉस होने पर बलक किया था ...
पीटर मैकएवॉय

दुर्भाग्य से, rd /sआंतरायिक रूप से भी विफल रहता है (यद्यपि प्रतीत होता है कि तुलना में अक्सर कम Remove-Item): github.com/Microsoft/console/issues/309
mklement

यह मेरे लिए ग द्वारा स्लैश पसंद नहीं करता है। क्या आपको इसे पॉवरशेल -कम से पहले करना होगा और सिंगल को cmd.exe भाग को उद्धृत करना होगा? मुझे "आप '/' ऑपरेटर के बाद एक मूल्य अभिव्यक्ति प्रदान करना चाहिए।" "अभिव्यक्ति या बयान में अप्रत्याशित टोकन 'c'। इसके सामने शक्तियां -कमांड के साथ भी ऐसा ही है। क्या भागने की जरूरत है?
मिशेल

7

ETA 20181217: PSVersion 4.0 और बाद में अभी भी कुछ परिस्थितियों में विफल हो जाएगा, मेहरदाद मिरेज़ा द्वारा वैकल्पिक उत्तर देखें , और mklement द्वारा दायर बग रिपोर्ट

mklement इस SO उत्तर पर कॉन्सेप्ट सॉल्यूशन का प्रूफ प्रदान करता है , क्योंकि बग को एक आधिकारिक फिक्स का इंतजार है

PowerShell( PSVersion 4.0) के नए संस्करण ने इस समस्या को पूरी तरह से हल कर दिया है और Remove-Item "targetdirectory" -Recurse -Forceबिना किसी समय की समस्याओं के काम करता है।

आप $PSVersiontableISE या PowerShellप्रॉम्प्ट के भीतर से चलाकर अपने संस्करण की जाँच कर सकते हैं । 4.0 वह संस्करण है जो जहाजों के साथ Windows 8.1और Server 2012 R2, और इसे विंडोज के पिछले संस्करणों पर भी स्थापित किया जा सकता है।


5
अभी भी मेरे लिए
पावरशेल

10
अभी भी PowerShell v5 में होता है !!!!! ११ !! १! १ !!!
रिचर्ड हौएर


2
@JamesCW मैंने rdसंस्करण में बदल दिया है । वास्तव में काम करने के अलावा, यह लगभग 3x तेज है
रिचर्ड हैर

समस्या को Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1 के रूप में ठीक नहीं किया गया है - इस बग रिपोर्ट को देखें । हालांकि rd /sकम बार विफल हो सकता है, यह भी टूट गया है - इस बग रिपोर्ट देखें
14

4

अद्यतन : लगता है कि विंडोज फाइलसिस्टम-आइटम हटाने की एपीआई को तुल्यकालिक बनाने की योजना है, लेकिन वे अभी तक विंडोज 10 संस्करण 1903 के समान नहीं हैं - GitHub पर यह टिप्पणी देखें ।


मौजूदा जवाब समस्या को कम करते हैं, ताकि यह कम बार हो, लेकिन वे मूल कारण को संबोधित नहीं करते हैं , यही कारण है कि विफलताएं अभी भी हो सकती हैं।

Remove-Item -Recurseअप्रत्याशित रूप से अतुल्यकालिक है , अंततः क्योंकि फ़ाइल और निर्देशिका को हटाने के लिए विंडोज एपीआई तरीके स्वाभाविक रूप से अतुल्यकालिक हैं और Remove-Itemइसके लिए कोई खाता नहीं है।

यह रुक-रुक कर, अप्रत्याशित रूप से दो तरीकों में से एक में प्रकट होता है:

  • आपका मामला: किसी गैर-रिक्त निर्देशिका को निकालना स्वयं विफल हो सकता है, यदि मूल उपनिर्देशिका को हटाने का प्रयास अभी तक पूरा नहीं हुआ है और इसमें अभी तक कोई उपनिर्देशिका या फ़ाइल नहीं है।

  • कम सामान्यतः: हटाने के तुरंत बाद हटाए गए निर्देशिका को फिर से बनाना विफल हो सकता है, क्योंकि हटाने को अभी तक पूरा नहीं किया जा सकता है जब तक कि पुनः निर्माण का प्रयास नहीं किया जाता है।

समस्या केवल PowerShell का नहीं प्रभावित करता है Remove-Item, लेकिन यह भी cmd.exe's rd /sनेट के रूप में रूप में अच्छी तरह[System.IO.Directory]::Delete() :

जैसा कि Windows PowerShell v5.1 / PowerShell Core 6.2.0-पूर्वावलोकन cmd.exe.1 / 10.0.17134.407 / .NET फ्रेमवर्क 4.7.03056, .NET कोर 2.1, न तो Remove-Item, न ही rd /s, और न ही [System.IO.Directory]::Delete()मज़बूती से काम करें , क्योंकि वे एसिंक्रोनस के लिए खाते में विफल रहते हैं विंडोज एपीआई फ़ाइल / निर्देशिका-हटाने के कार्यों का व्यवहार :

एक कस्टम PowerShell फ़ंक्शन के लिए जो एक मज़बूती से सिंक्रोनस वर्कअराउंड प्रदान करता है , यह SO उत्तर देखें


जब हटाने वाली फ़ाइलों को संभालना निश्चित है:while($true) { if ( (Remove-Item [...] *>&1) -ne $null) { Start-Sleep 0.5 } else { break } }
२३:५५

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
यह अच्छा है लेकिन मुझे अभी भी इससे समस्या थी। यदि mkdir कमांड सिस्टम को rm कमांड पूरा करने से पहले चलाता है, तो वह System.UnauthorizedAccessException को पूरी तरह से ItemExistsUnauthorizedAccessError के एकQQualifiedErrorId के साथ फेंक सकता है। यानी, ओएस द्वारा निर्देशिका को अभी तक हटाया नहीं गया है (मेरी धीमी एचडीडी पर)। ताकि त्रुटि को भी पकड़ा जा सके। और यह एक नॉन-टर्मिनेटिंग त्रुटि है, इसलिए ErrorAction को स्टॉप पर सेट करना होगा। मैं कोशिश ब्लॉक में भी rm कमांड डालता हूं, बस ऐसे मामलों में जब हटाने के दौरान क्षणिक IO त्रुटियां होती हैं।
मार्क लापिएरे

मैं विश्वास नहीं कर सकता यह भी किया जाना है। धिक्कार है, पॉवरशेल चूसता है!
जूलम

3

निर्देशिका और उसकी सामग्री को हटाने के लिए दो चरण होते हैं। पहले सामग्री को हटाएं, फिर फ़ोल्डर को ही। दोषपूर्ण पुनरावर्ती निकालें आइटम के लिए समाधान का उपयोग करना समाधान इस तरह दिखेगा:

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

इस तरह आप मूल निर्देशिका को भी हटा सकते हैं।


1
यह वही है जो स्वीकार किए गए उत्तर ने कहा। क्या आपके पास जोड़ने के लिए कुछ है?
माइकल हैम्पटन

1
वे इंगित कर रहे हैं कि स्वीकृत उत्तर स्वयं निर्देशिका को नहीं हटाता है, इसलिए इसमें दो चरण हैं।
पॉल जॉर्ज

2
Remove-Itemअपने पाइपिंग आदेश में एक ही समस्या है कि मूल रूप से कहा गया है। यह एक निर्देशिका आइटम पर ठोकर खा सकता है जो उसी तरह गैर-खाली है।
देजन

@Dejan यह निर्देशिका अभी भी खाली नहीं हो सकती है यदि इस कोड की पहली पंक्ति काम करती है, क्या यह हो सकता है?
इफिडी ओकोनकोव

1
हालांकि यह विफलता की संभावना को कम कर सकता है , यह अभी भी विफल हो सकता है, यह देखते हुए कि Remove-Item -Recurseअभी भी शामिल है। अंतर्निहित समस्या अभी भी Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1 के रूप में मौजूद है - इस बग रिपोर्ट को देखें
mklement

3

भगवान। जवाब के बहुत सारे। मैं ईमानदारी से उन सभी में से एक को पसंद करता हूं। यह सुपर सरल, पूर्ण, पठनीय और किसी भी विंडोज मशीन पर काम करता है। यह .NET (विश्वसनीय) पुनरावर्ती डिलीट कार्यक्षमता का उपयोग करता है और यदि यह किसी कारण से विफल हो जाता है, तो यह एक उचित अपवाद फेंकता है जिसे एक कोशिश / कैच ब्लॉक के साथ संभाला जा सकता है।

$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 के रूप में मौजूद है - इस बग रिपोर्ट को देखें
14


0

मेरे पास एक निर्देशिका के साथ यह मुद्दा था जो नहीं हटेगा। मैंने पाया कि एक सबफ़ोल्डर भ्रष्ट था और जब मैंने उस बच्चे को स्थानांतरित करने या उसका नाम बदलने की कोशिश की तो मुझे एक त्रुटि संदेश मिला, जिसके बारे में कुछ कहा जा रहा है कि वह गायब है। मैंने rm -Force का उपयोग करने की कोशिश की और आपको जैसी त्रुटि मिली, वैसा ही किया।

मेरे लिए जो काम किया वह 7-ज़िप का उपयोग करके "कंप्रेशन के बाद फाइल हटाएं" विकल्प के साथ पेरेंट डायर को कंप्रेस कर रहा था। एक बार जब यह संकुचित हो गया तो मैं ज़िप फ़ाइल को हटाने में सक्षम हो गया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.