सबट्री में सभी खाली निर्देशिकाओं को कैसे निकालें?


151

मैं एक सबट्री में सभी खाली निर्देशिकाओं को कैसे हटा सकता हूं? मैंने कुछ ऐसा इस्तेमाल किया

find . -type d -exec rmdir {} 2>/dev/null \;

लेकिन मुझे केवल खाली निर्देशिका वाली निर्देशिकाओं को हटाने के लिए कई बार चलाने की आवश्यकता है। इसके अलावा, यह काफी धीमा है, खासकर साइबरविन के तहत।


जवाबों:


221

जीएनयू findविकल्पों को मिलाकर और भविष्यवाणी करता है, इस कमांड को काम करना चाहिए:

find . -type d -empty -delete
  • -type d निर्देशिकाओं के लिए प्रतिबंधित करता है
  • -empty खाली लोगों को प्रतिबंधित करता है
  • -delete प्रत्येक निर्देशिका को निकालता है

पेड़ को पत्तों से चलने की आवश्यकता के बिना निर्दिष्ट -depthकिया जाता है क्योंकि यह निहित है -delete


2
-deleteपहले से ही इसका तात्पर्य -depthहै कि आपको मैन्युअल रूप से निर्दिष्ट करने की आवश्यकता नहीं है।
जमदग्नि

1
धन्यवाद, मुझे यह महसूस नहीं हुआ। उत्तर अपडेट किया गया।
क्रिस्टोफ़ ड्रेव-ड्रगेट

11
मैं -mindepth 1यहां जोड़ूंगा, शुरुआती निर्देशिका को हटाने से रोकने के लिए, अगर यह खाली होगा।
ग्रेग डबकी

2
महान, लेकिन मेरे पुराने SunOS होस्ट पर काम नहीं करता है ...
dokaspar

2
!खोल के लिए एक विशेष अर्थ है। आपको इससे बचने की जरूरत है। कुछ इस तरह: \! -name 'Completed'पहले -deleteकाम करना चाहिए। या आप बस इस निर्देशिका में एक मार्कर फ़ाइल डालते हैं।
क्रिस्टोफ ड्रेवेट-ड्रोगेट

53

निर्देशिका को गहराई से नेस्टेड-पहले सूचीबद्ध करें।

find . -depth -type d -exec rmdir {} \; 2>/dev/null

(ध्यान दें कि पुनर्निर्देशन findएक पूरे के रूप में कमांड पर लागू होता है , केवल करने के लिए नहीं rmdir। केवल पुनर्निर्देशन rmdirएक महत्वपूर्ण मंदी का कारण होगा क्योंकि आपको एक मध्यवर्ती शेल को लागू करने की आवश्यकता होगी।)

खोजने के rmdirलिए -emptyविधेय पास करके आप गैर-खाली निर्देशिकाओं पर चलने से बच सकते हैं। जब यह कमांड चलने वाला होता है, तो GNU निर्देशिका का परीक्षण करता है, इसलिए अभी खाली की गई निर्देशिका को उठाया जाएगा।

find . -depth -type d -empty -exec rmdir {} \;

तेजी लाने का एक और तरीका यह होगा कि rmdirइनवोकेशन को ग्रुप बनाया जाए । दोनों मूल रूप से, विशेष रूप से सिग्विन के तहत तेजी से ध्यान देने योग्य होने की संभावना है। मुझे इन दोनों के बीच बहुत अंतर की उम्मीद नहीं है।

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null

कौन सी विधि तेज है यह इस बात पर निर्भर करता है कि आपके पास कितने गैर-खाली निर्देशिका हैं। आप -emptyइनवॉइस को समूहीकृत करने के तरीकों के साथ गठजोड़ नहीं कर सकते , क्योंकि तब जो निर्देशिका केवल खाली निर्देशिका होती है, वे समय findपर खाली नहीं दिखतीं ।

एक और तरीका कई पासों को चलाने का होगा। क्या यह तेज है, बहुत सारी चीजों पर निर्भर करता है, जिसमें यह भी शामिल है कि क्या पूरी निर्देशिका पदानुक्रम डिस्क कैश में findरन के बीच रह सकती है ।

while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done

वैकल्पिक रूप से, zsh का उपयोग करें। ग्लोब क्वालीफायर F गैर खाली निर्देशिका से मेल खाता है, तो /^Fखाली निर्देशिका से मेल खाता है। केवल खाली निर्देशिका वाले निर्देशिकाओं का इतनी आसानी से मिलान नहीं किया जा सकता है।

while rmdir **/*(/N^F); do :; done

(यह तब समाप्त होता है जब rmdirएक खाली कमांड लाइन प्राप्त होती है।)


बस। 90 सेकंड के बजाय यह 0.90 सेकंड लेता है।
मआर्टिनस

@maaartinus: मैं उत्सुक हूं: क्या आपके पास एक समान डेटा सेट है जहां आप बिना कोशिश कर सकते हैं -p? मुझे नहीं लगता था कि इससे कोई फर्क पड़ेगा।
गाइल्स

3
@maartinus - अन्य छोटी अनुकूलन: जोड़ना -emptyइस के साथ काम करना चाहिए (हालांकि मुझे यकीन नहीं है कि यह वास्तव में कितना लाभ प्राप्त करेगा)। और बहुत, बहुत तुच्छ, क्योंकि आप शायद नहीं निकालना चाहते हैं ., का उपयोग करें -mindepth 1

यह निष्कासन नहीं था, लेकिन प्रक्रिया शुरू हो गई है, जो लगभग हर समय हुई। मैंने उस -depthतर्क को नजरअंदाज कर दिया था , जो rmdir -pबेकार हो जाता है। मैंने अपनी टिप्पणी पहले ही बदल दी है। 90 का दशक मेरा मूल प्रयास था; यहां कुछ भी आश्चर्यजनक नहीं है।
मारार्टिनस

2
मैंने महसूस किया कि हम rmdirकम से कम GNU के साथ कमांड कमांड को पूरी तरह से हटा सकते हैं, इस कमांड के साथ:find . -depth -type d -empty -delete
क्रिस्टोफ ड्रेवेट-ड्रोगेट

6

यदि आप बस -pअपने से निपटते हैं rmdir, तो वह एक पास में काम करेगा। यह सुंदर या इष्टतम नहीं होगा, लेकिन इसे सब कुछ मिलना चाहिए। जो rmdir को आपके द्वारा हटाए जा रहे किसी भी गैर-खाली मूल निर्देशिका को हटाने के लिए कहता है।

आप -emptyखोजने के लिए परीक्षण को जोड़कर थोड़ा बचा सकते हैं, इसलिए यह गैर-रिक्त निर्देशिकाओं से परेशान नहीं करता है।


3

find . -depth -type d -exec rmdir {} +

इस सवाल का सबसे सरल और मानक अनुपालन उत्तर है।

यहां दिए गए अन्य उत्तर दुर्भाग्य से सभी विक्रेता विशिष्ट एन्हांसमेंट पर निर्भर करते हैं जो सभी प्रणालियों पर मौजूद नहीं हैं।


3
यह उत्तर प्रत्येक निर्देशिका के लिए एक त्रुटि उत्पन्न करता है जिसे हटाया नहीं जा सकता है जो वांछनीय से कम हो सकता है।
विलेम वैन केटविच

0

find . -type d -printf "%d %p\n" |\ sort -nr |\ perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done

यहां देखिए यह कैसे काम करता है:

  1. अपनी गहराई के साथ सभी निर्देशिकाओं को पुन: सूचीबद्ध करें
  2. उनकी गहराई के क्रम को क्रमबद्ध करके
  3. केवल निर्देशिका पथ को फ़िल्टर करें
  4. rmdirसूची को एक-एक करके चलाएं

0

मैं अक्सर इस्तेमाल किए जाने वाले findआदेशों के लिए इन उपनामों का उपयोग करता हूं , खासकर जब मैं डुप्गुरु का उपयोग करके डिस्क स्थान की सफाई करता हूं , जहां डुप्लिकेट को हटाने से बहुत सारी खाली निर्देशिकाएं हो सकती हैं।

अंदर की टिप्पणियाँ .bashrcतो मैं उन्हें बाद में भूल नहीं पाऊंगा जब मुझे इसे ट्विक करने की आवश्यकता होगी।

# find empty directories
alias find-empty='find . -type d -empty'

# fine empty/zero sized files
alias find-zero='find . -type f -empty'

# delete all empty directories!
alias find-empty-delete='find-empty -delete'

# delete empty directories when `-delete` option is not available.
# output null character (instead of newline) as separator. used together
# with `xargs -0`, will handle filenames with spaces and special chars.
alias find-empty-delete2='find-empty -print0 | xargs -0 rmdir -p'

# alternative version using `-exec` with `+`, similar to xargs.
# {}: path of current file
# +: {} is replaced with as many pathnames as possible for each invocation.
alias find-empty-delete3='find-empty -exec rmdir -p {} +'

# for removing zero sized files, we can't de-dupe them automatically
# since they are technically all the same, so they are typically left
# beind. this removes them if needed.
alias  find-zero-delete='find-zero -delete'
alias find-zero-delete2='find-zero -print0 | xargs -0 rm'
alias find-zero-delete3='find-zero -exec rm {} +'

-2

rm -r */कमांड ने मेरे लिए आसानी से काम किया। फ़ाइलों के साथ निर्देशिकाओं को जबरदस्ती हटाने की rmआवश्यकता होनी चाहिए -frm -rकेवल खाली निर्देशिका निकालनी चाहिए। मैं खुला हूं कि यह गलत क्यों हो सकता है। यह भी फ़ाइलों को छोड़ देना चाहिए क्योंकि */केवल फ़ोल्डर्स को देखता है।


1
मैं दृढ़ता से इसे पहले अच्छी तरह से परखने की सलाह दूंगा क्योंकि rmयह मुख्य रूप से फाइलों को हटाने के लिए है। जबकि */केवल निर्देशिकाओं से मेल खाता है, मुझे नहीं पता कि यह गहरे स्तरों पर क्या करता है। मैं यह भी सोच सकता हूं कि यह केवल कुछ प्रणालियों पर काम करता है।
माॅर्टिनस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.