2013-03-06 7 views
6

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

Initial State:      Desired Output: 

\         \ 
|_Folder1       |_Folder1 
| |_File1.txt       |_SubFolder1 
| |_File2.xml       |_File3.csv 
| |_SubFolder1       |_File4.exe 
| | |_File3.csv 
| | |_File4.exe 
| |_Subfolder2 
|_Folder2 
| |_ <more files here> 
|_Folder3 (etc) 

तो यहाँ मैं क्या करने की कोशिश की है:

Remove-Item * -exclude Folder1\Subfolder1\* 

और मैं इस तरह की एक चेतावनी मिलती है:

Confirm 
The item at C:\foo\Folder1 has children and the -recurse parameter was not specified. 
If you continue, all children will be removed with the item. Are you sure you want to continue? 
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help 
(default is "Y"): 

जब मैं -recurse निर्दिष्ट करने पर, हर फ़ाइल को हटा देता है, और उपेक्षा करने लगता है मेरी फिल्टर।

क्या चल रहा है, और यह करने का सही तरीका क्या है?

संपादित करें: मैंने एक ज़िप फ़ाइल शामिल की है जिसमें ऊपर के रूप में example folder structure है। यदि आप समाधान का परीक्षण करना चाहते हैं, तो कृपया इसके खिलाफ प्रयास करें। मैंने एक दूसरी ज़िप फ़ाइल भी शामिल की है जिसमें desired output है, ताकि आप यह जांच सकें कि यह काम कर रहा है या नहीं।

उत्तर

5

हो सकता है कि वहाँ एक सरल समाधान है, लेकिन इस समारोह चाल करना चाहिए:

function Clean-Folder 
{ 
    param(
     [string]$rootfolder, 
     [string[]]$excluded 
    ) 
    $rootfolder = resolve-path $rootfolder 
    Push-Location $rootFolder 
    if($excluded -notmatch "^\s*$") 
    { 
     $excluded = Resolve-Path $excluded 
    } 
    $filesToDel = Get-ChildItem $rootFolder -Recurse 
    # Excluding files in the excluded folder 
    foreach($exclusion in $excluded) 
    { 
     $filesToDel = $filesToDel |?{$_.fullname -notlike ("{0}\*" -f $exclusion)} 
     # Excluding parent folders of the excluded folder 
     while($exclusion -notmatch "^\s*$") 
     { 
      $filesToDel = $filesToDel |?{$_.fullname -ne $exclusion} 
      $exclusion = Split-Path -parent $exclusion 
     } 
    } 
    $filesToDel |Remove-Item -Recurse -ErrorAction SilentlyContinue 
    Pop-Location 
} 

असल में, यह आपके फ़ोल्डर में सभी आइटमों को दोबारा सूचीबद्ध करता है, फिर उस को हटा दें जिसे आप रखना चाहते हैं, इसके उप-आइटम और उसके सभी मूल फ़ोल्डर्स। अंत में, यह शेष सूची हटा देता है।

बस ऊपर समारोह का ऐलान करते हैं तो:

Clean-Folder -rootfolder <path> -excluded <folder you want to exclude> 

संपादित करें: बनाया rootfolder संबंधित पथ स्वीकार करते हैं, और बाहर किए गए फ़ोल्डरों

+0

अच्छा काम @poorkenny! यह निश्चित रूप से अब तक का सबसे नज़दीक है, और केवल एक ही जो मेरे आवश्यक आउटपुट से मेल खाता है। हालांकि कुछ सुझाव: क्या "निकालें" पैरामीटर कार्य को "निकालें-आइटम" के लिए एक तरीका बनाने का कोई तरीका है (यानी एक पथ के बजाए बहिष्कृत की अल्पविराम से अलग सरणी लें)। पूर्ण लोगों की बजाय सापेक्ष पथों को अनुमति देना भी अच्छा होगा। – NeilD

+0

हो गया। मैंने व्यापक परीक्षण नहीं किया है, लेकिन ऐसा लगता है कि यह चाल चल रहा है ... – Poorkenny

+0

कूल। माइक्रोसॉफ्ट से एक गैर-टूटी-रिकर्स पैरामीटर की अनुपस्थिति में, मैं इसे सही उत्तर के रूप में चिह्नित कर रहा हूं। – NeilD

0

मैं एक सही या सही तरीका नहीं दे सकता, लेकिन मैंने कामकाज के बारे में सोचा था। पर बाहर निकालने के अपने

get-childitem -Recurse | where fullname -notlike *SubFolder1* | remove-item -recurse 
+0

कि काम नहीं करेगा, क्योंकि Folder1 आपके फ़िल्टर द्वारा बहिष्कृत नहीं किया गया है, जिससे इसे रिकर्सली हटा दिया जा सकता है, जो बदले में सबफ़ोल्डर 1 – Poorkenny

+0

हटा देता है, मैं वही चीज़ पोस्ट करने वाला था। यह नीचे-नीचे की बजाय ऊपर-नीचे से प्राप्त करने वाले आइटम को हटाने और निकालने की तरह है ... – NeilD

+0

आह, मैंने सोचा था कि आप "फ़ोल्डर 1" –

0

बस ऐसे ही वाइल्डकार्ड खाई:

आप (ताकि कुछ मामूली समायोजन की आवश्यकता हो सकती विशेष रूप से परीक्षण नहीं) को हटाने के आइटम cmdlet के लिए एक get-childitem cmdlet के आउटपुट पाइप की कोशिश कर सकते निकालें-मद * -exclude Folder1 \ Subfolder1 \

+1

नोप के भीतर से आदेश चला रहे थे, काम नहीं करता ... :( – NeilD

+0

वैसे यह मेरी मशीन पर काम करता है ... :) –

+0

हम्म ... मैंने उपरोक्त उदाहरण की नकल करने वाली एक डमी फ़ोल्डर संरचना बनाई है। यह मेरे ड्रॉपबॉक्स पर है: https: //dl.dropbox.com/u/15385515/foo.zip ... जब मैं वाइल्डकार्ड के बिना अपना कमांड चलाता हूं, तब भी मुझे सभी फ़ोल्डर्स हटा दिए जाते हैं। क्या आप इसे आजमा सकते हैं? – NeilD

7
(Get-ChildItem c:\folder1\ -recurse | select -ExpandProperty fullname) -notlike 'c:\folder1\subfolder1*' | sort length -descending | remove-item 
+0

+1 के साथ फ़िल्टर सरणी के लिए +1, और इस तरह की चाल! बहुत अच्छा। –

+0

इसे केवल एक बदलाव की आवश्यकता है: 'c: \ folder1 \ subfolder1 *' –

+0

हो गया। अच्छी पकड़! – mjolinor

1

आप लगातार दो आदेशों कह सकते हैं की एक सूची स्वीकार करते हैं:

Remove-Item * -recurse -exclude Folder1 
Remove-Item Folder1\* -recurse -exclude Subfolder1 

सबसे पहले आप फ़ोल्डर 1 को छोड़कर सब कुछ हटा दें। इसके बाद आप Subfolder1 को छोड़कर फ़ोल्डर 1 में सब कुछ हटा दें। इस तरह आप बाहर निकलने के लिए सबबफॉल्डर निर्दिष्ट करने से बचें।

0

मैं एक ही समस्या थी और अंत में मैं इसे हल किया है:

Get-Childitem folder_for_clear_path -Exclude folder_for_exclude_name | Remove-Item -Recurse 

संपादित: इस मुद्दे के लिए, अगले कोड का उपयोग करें:

Get-Childitem C:\foo -exclude Folder1 | Remove-Item -recurse 
Get-Childitem C:\foo\Folder1 -exclude SubFolder1 | Remove-Item -recurse 
+0

यह मेरे लिए बिल्कुल काम नहीं करता है। मैं हर बार एक खाली रूट फ़ोल्डर के साथ समाप्त होता है। क्या आप एक सटीक वाक्यविन्यास दे सकते हैं जो उदाहरण संरचना के साथ काम करता है? – NeilD

+0

क्षमा करें। शुरुआत में मैं आपकी शर्तों को सही नहीं समझ पाया। कोड की अगली 2 पंक्तियां आपको तर्क की आवश्यकता होती है: यह 'get-childitem c: \ foo- फ़ोल्डर 1 को शामिल करें। निकालें-आइटम -recurse' और फिर यह 'get-childitem सी: \ foo \ फ़ोल्डर 1 - सबफ़ोल्डर 1 शामिल करें। निकालें-आइटम -recurse' – Vitaliy

+0

क्या यह आपके लिए सहायक है? – Vitaliy

संबंधित मुद्दे