`Find` आउटपुट के आधार पर निर्देशिकाओं को कैसे हटाएं?


148

मैं .svn निर्देशिकाओं को खोजने के लिए निम्नलिखित आदेश जारी करता हूं:

find . -name ".svn"

यह मुझे निम्नलिखित परिणाम देता है:

./toto/.svn
./toto/titi/.svn
./toto/tata/.svn

rm -frनिर्देशिकाओं और उनकी सामग्री को हटाने के लिए मैं इन सभी लाइनों को कैसे संसाधित कर सकता हूं ?


3
GNU खोज का -deleteविकल्प है।
मार्को

5
या आप खोज -exec rm -r "{}" \;के अंत में जोड़ सकते हैं - उपयोग करते समय सावधान रहें rm -r! :)
Drav Sloan

10
@Marco डिलीट ऑप्शन डायरेक्ट्रीज़ पर काम नहीं करता है।
अरनौद

@SuperChafouin यह पूरी तरह से फ़ाइलों और निर्देशिकाओं पर यहाँ काम करता है। मुद्दा यह है कि यह केवल खाली निर्देशिकाओं को हटाता है और जब आप -name ".svn"इसे निर्दिष्ट करते हैं तो यह केवल .svnनिर्देशिका से ही मेल खाता है न कि .svnनिर्देशिका में स्थित फाइलों से ।
मार्को

1
@SuperChafouin, लेकिन उनमें रिक्त स्थान वाले पथों के लिए काम नहीं करेगा (इसलिए -execउद्धृत के साथ उपयोग करना "{}")।
द्रविण

जवाबों:


194

ढूँढें -execप्रत्येक मिलान के लिए विकल्प के साथ तर्क निष्पादित कर सकता है। यह एक अनुशंसित तंत्र है क्योंकि आप रिक्त स्थान / newlines और उनमें अन्य वर्णों के साथ पथ को सही ढंग से संभाल सकते हैं। इससे पहले कि आप निर्देशिका में ही निकाल सकते हैं निर्देशिका की सामग्री को हटाने के लिए है, इसलिए का उपयोग करेगा -rके साथ rmइस लक्ष्य को हासिल करने के लिए आदेश।

अपने उदाहरण के लिए आप जारी कर सकते हैं:

find . -name ".svn" -exec rm -r "{}" \;

आप यह भी बता सकते हैं कि केवल निर्देशिकाओं को नाम दिया गया है। एक -type dचेक जोड़कर। Svn :

find . -name ".svn" -type d -exec rm -r "{}" \;

चेतावनी का उपयोग rm -rसावधानी के साथ यह फ़ोल्डर और उसकी सभी सामग्री को हटा देता है।

तुम सिर्फ खाली निर्देशिका के साथ ही निर्देशिका है कि केवल खाली निर्देशिका शामिल हटाना चाहते हैं, कर सकते हैं के साथ ही है कि लगता है -deleteऔर -empty:

find . -name ".svn" -type d -empty -delete

21
मैंने सलाह दी है कि हमेशा कमांड ढूंढने के -type बाद ही चलें -name, क्योंकि कॉल करने के statलिए टाइप महंगे हैं। मैंने अभी-अभी फाइलों के एक बड़े समूह पर खुद को आजमाया, और यह सच प्रतीत होता है: दौड़ने find . -name 'foo' -type dमें 19 सेकंड लगे, जबकि find . -type d -name 'foo'32 सेकेंड लगे। तो -typeपहले चलाने के लिए लगभग 50% अधिक समय ।
पालक

6
मैं वर्षों से इस आदेश का उपयोग कर रहा हूं, लेकिन अब मैक पर मुझे यह कहते हुए त्रुटियां हो रही हैं कि उन निर्देशिकाओं का अस्तित्व नहीं है। भले ही यह उन्हें हटाता है। मैंने पहले कभी संदेश नहीं देखे।
चॉवी

1
@Chovy के समान। क्या इन संदेशों से छुटकारा पाने का कोई तरीका है?
क्लेमेंट

2
@chovy @ clément, क्योंकि findअन्य मैचों के लिए उस फ़ोल्डर में देखना चाहता है, जबकि यह उसी समय फ़ोल्डर को हटा रहा है। ~ मुझे अभी तक यह पता नहीं है कि इसे कैसे ठीक किया जाए। ~ डर्टी फिक्स:find . -name "folder-to-delete" -print0 | xargs -r0 -- rm -r
चार्ली

5
@chovy @ क्लेमेंट मुझे लगता है कि -depthतर्क इसे ठीक करता है:find . -depth -name ".svn" -type d -exec rm -r "{}" \;
गिंबोलैंड

67

यहाँ एक पोर्टेबल अभी भी स्वीकृत उत्तर मार्ग की तुलना में तेज़ है।

एक का प्रयोग +के रूप में एक अर्धविराम के बजाय findकमांड टर्मिनेटर CPU उपयोग के अनुकूलन है। यदि आपके पास बहुत सारी .svnउप-निर्देशिकाएं हैं, तो यह महत्वपूर्ण हो सकता है :

find . -name .svn -type d -exec rm -rf {} +

यह भी ध्यान दें कि आप कभी नहीं 1 घुंघराले ब्रेसिज़ यहाँ उद्धृत करने के लिए की जरूरत है।

1 जब तक आप fishशेल का उपयोग नहीं करते हैं।


5
+ और अर्धविराम के बीच क्या अंतर है? क्यों हम घुंघराले ब्रेसिज़ का उपयोग नहीं करते हैं?
शिचेंग गुओ

1
@ शिखेंगगूओ सेमीकॉलन के साथ, प्रति डायरेक्टरी मिली एक आरएम कमांड होगी, + एक आरएम कमांड के साथ सभी डायरेक्ट्रीज (या कम से कम बहुत बड़ी संख्या में) सभी डाइरेक्टरी को प्रोसेस करेगा। मुझे आपका दूसरा सवाल नहीं आता है, घुंघराले। यहाँ ब्रेसिज़ का उपयोग किया जाता है।
जलेगीरे

मुझे लगता है कि @ शिखेंगगू का मतलब है कि हमें यहां घुंघराले ब्रेसों को उद्धृत करने की आवश्यकता क्यों नहीं है (@jlliagre ने लिखा है कि हमें उन्हें उद्धृत करने की आवश्यकता नहीं है)। मुझे अब एक संदर्भ नहीं मिल रहा है, लेकिन मैं समझता हूं कि क्योंकि यह स्वतः ही {} के लिए बदले गए रास्तों से बच जाएगा।
क्विन कॉमेंडेंट

जवाब और सवाल क्या + क्या करता है पर बिल्कुल सही नहीं हैं। अगर कई फाइलें मिल जाती हैं तो ';' 'कमांड लाइन को बहुत लंबी' त्रुटि देगा। + बैचों में पाई जाने वाली फ़ाइलों को विभाजित करता है जो अधिकतम अनुमत कमांड लाइन की लंबाई से कम होती हैं और प्रत्येक बैच के लिए कमांड को चलाती हैं।
गाएथे

1
@gaoithe मैंने आपको रोलबैक किया जो एक सही कथन को गलत के साथ बदल देता है। का उपयोग + करता है CPU उपयोग को कम करने, का उपयोग ; नहीं करता है एक कमांड बहुत लंबा त्रुटि के लिए सीसा।
जलियागरे

27

मान लें कि आप ग्नू खोज का उपयोग कर रहे हैं , आप -deleteविकल्प का उपयोग कर सकते हैं :

find . -name test -delete

जो याद रखना आसान है।


कमांड के स्पष्टीकरण के साथ अपनी पोस्ट का विस्तार करने पर विचार करें (या अपने समाधान का प्रलेखन करने के लिए)। अक्सर एक (या दो) लाइन उत्तर सबसे अधिक रोशन नहीं होते हैं।
हेलोसिहॉस्ट

93
यह गैर-रिक्त निर्देशिकाओं पर काम नहीं करता है।
बेलाक्वा

2
मैक ओएस एक्स पर भी काम करता है
ड्रा करें

इस गैर खाली फ़ोल्डर के लिए काम नहीं करता है, लेकिन यह आसान और सुरक्षित समाधान है
RousseauAlexandre

विकल्प ऑर्डर बहुत महत्वपूर्ण है, उन्हें क्रम में निष्पादित करेंगे, -इसलिए अंतिम एक होना होगा
जोस इग्नासियो सेंटेनो

13

मेरे कंप्यूटर पर जब मैं उपयोग करता हूं:

find . \( -name dirname -type d \) -exec rm -r '{}' ';'

निर्देशिकाएं हटा दी जाती हैं, लेकिन मुझे त्रुटि मिलती है:

find: ‘./dirname’: No such file or directory

प्रत्येक निर्देशिका के लिए।

मेरी निर्देशिकाएँ खाली नहीं हैं, इसलिए -delete विकल्प मेरे लिए काम नहीं करेगा। मुझे इस व्यवहार का कारण यहाँ मिला :

  1. लगता है (जरूरी नहीं) में पहली प्रविष्टि ./ निर्देशिका है। यह होगा dir.1 /
  2. यह 'dir?' पैटर्न से इसकी तुलना करता है। क्या यह मेल खाता है? हाँ।
  3. "rm -r dir.1" निष्पादित करें।
  4. निर्देशिका में पैटर्न खोजने के लिए dir.1 / दर्ज करने का प्रयास करें। यह कमांड कमांड के बारे में कुछ भी नहीं जानता है।
  5. यह dir.1 / अब नहीं मिलता है। रिटर्न रिटर्न (स्ट्रेस आउटपुट को देखें)

मैंने इसके बजाय काम करने के लिए इसका इस्तेमाल किया:

rm -r `find . -name dirname -type d`

ध्यान रखें कि खोज अभी भी dirname नामक निर्देशिकाओं में पुनरावृत्ति करने का प्रयास करेगी, जो वास्तव में आवश्यक नहीं है और कुछ अतिरिक्त समय लगेगा। अपनी निर्देशिका संरचना के आधार पर, आप --depthखोज विकल्प के साथ इसके आसपास काम करने में सक्षम हो सकते हैं। इसके अलावा, यदि आपके पास dirname / foo / dirname जैसी निर्देशिका संरचना है, तो आपको rm से "ऐसी कोई फ़ाइल या निर्देशिका" त्रुटियां नहीं मिलेंगी। त्रुटियों को दबाने के लिए आप stderr को / dev / null में या -frm के साथ (बल) ध्वज का उपयोग कर सकते हैं ।


2
बुरा विचार: रिक्त स्थान के साथ फ़ाइल का नाम भयानक मुद्दों के सभी प्रकार का कारण होगा
Clément

2
भविष्य के पाठकों के लिए: find . -name "to-delete" -print0 | xargs -r0 -- rm -rएक विफल संस्करण है जो रिक्त स्थान पर क्रैश नहीं करता है
चार्ली

3
देखें unix.stackexchange.com/a/115869/8257 आपको जोड़ना होगा -prune
1

1
-prune"ऐसी कोई फ़ाइल या निर्देशिका" त्रुटि से बचने के लिए जोड़ें ।
जूलियन कार्सिक

12

ऐसा करने का एक तेज़ तरीका है:

find . -name ".svn" -type d -prune -exec rm -rf '{}' '+'

मामले में आपके पास ".svn" दूसरे के अंदर ".svn" है।


यदि आप निर्देशिकाओं को उप-निर्देशिकाओं के साथ हटाना चाहते हैं तो यह बहुत उपयोगी नहीं है।
एलेक्सिस विलके

5

बैश विशिष्ट समाधान:

shopt -s globstar
rm -r **/.svn
shopt -u globstar #optional. this will disable globstar expansion

3
ग्लब्स की कमांड लाइन विस्तार के लिए ध्यान दें जो कई फाइलों से मेल खाते हैं, इस तंत्र के साथ मेल खाने वाली फ़ाइलों की संख्या की एक सीमा है। इस सीमा से अधिक होने परbash: /bin/rm: Argument list too long
Drav Sloan

1
@DravSloan सही है, लेकिन वह सीमा सैकड़ों-हजारों फाइलों में है। यह कुछ को ध्यान में रखना है, लेकिन शायद ज्यादातर लोगों के लिए एक समस्या नहीं होगी।
evilsoup

4

मैंने पाया है कि -deleteकार्रवाई -pathपरीक्षण के साथ अच्छी तरह से काम करती है । उदाहरण के लिए, निम्नलिखित को मूल पोस्टर समस्या पर काम करना चाहिए:

find . -path '*/.svn*' -delete

क्या आपको यकीन है? -deleteतात्पर्य है -depth, और यह सुनिश्चित करता है कि मेरे सिस्टम पर गैर-खाली निर्देशिकाओं को हटा दिया जाए।
मैग्नस

सेवानिवृत्त और यह काम करता है। शायद यह सिर्फ टाइपो था जिसे मैंने ठीक कर दिया है।
kenorb

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