टर्मिनल से एक फ़ाइल को छोड़कर एक निश्चित एक्सटेंशन वाली फ़ाइलों को हटाना


36

मुझे "filename.gif" नाम के साथ एक फ़ाइल को छोड़कर .gif एक्सटेंशन के साथ सभी फ़ाइलों को निकालने की आवश्यकता है। टर्मिनल में ऐसा करने का इष्टतम तरीका क्या है?

कमांड rm *.gifफाइल सहित सभी gif फाइल को हटा देता है filename.gif

जवाबों:


66

यहाँ सरल उपाय है जो आपको संभवतः उपयोग करना चाहिए:

mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif

.keepविस्तार के बारे में कुछ खास नहीं है , यह सिर्फ इसलिए बनाता है ताकि फ़ाइलनाम अस्थायी रूप से समाप्त न हो .gif

यदि आपको फ़ाइल का नाम नहीं बदलना चाहिए (और ऐसी स्क्रिप्टिंग स्थितियाँ हैं जहाँ यह महत्वपूर्ण है):

for X in *.gif; do
    if [ "$X" != "filename.gif" ]; then
        rm "$X"
    fi
done

या आप इसे इस तरह छोटा लिख ​​सकते हैं:

for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done

आप findइसके बजाय उपयोग करना पसंद कर सकते हैं ; यह बहुत शक्तिशाली है, आप इसे अधिक पठनीय मान सकते हैं , और यह उन जैसे पात्रों के साथ अजीब फ़ाइलनाम को* बेहतर ढंग से संभालता है

find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete

मैंने -notऑपरेटर को पठनीयता के लिए उपयोग किया है, लेकिन अगर POSIX अनुपालन महत्वपूर्ण है - यदि आप GNU खोज का उपयोग नहीं कर रहे हैं, या यदि यह एक स्क्रिप्ट के लिए है तो आप दूसरों को पुनर्वितरित करने या विभिन्न प्रणालियों पर चलने का इरादा रखते हैं - आपको चाहिए !इसके बजाय ऑपरेटर का उपयोग करें :

find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete

इसके बारे findमें एक आसान बात यह है कि आप केस-असंवेदनशीलता के लिए कमांड को आसानी से संशोधित कर सकते हैं, ताकि यह एक्सटेंशन जैसी फ़ाइलों को .GIFभी ढूंढे और हटाए :

find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete

कृपया ध्यान दें कि मैंने खोज पैटर्न -inameके -nameलिए उपयोग किया है *.gifलेकिन मैंने इसके लिए उपयोग नहीं किया है filename.gif। संभवतः आपको पता है कि आपकी फ़ाइल को क्या कहा जाता है, और -inameन केवल विस्तार में , बल्कि फ़ाइल नाम में कहीं भी वैकल्पिक पूंजीकरण से मेल खाएगा ।

ये सभी समाधान केवल वर्तमान निर्देशिका में तुरंत रहने वाली फ़ाइलों को हटाते हैं । वे वर्तमान निर्देशिका में निहित फ़ाइलों को नहीं हटाते हैं, और वे उन फ़ाइलों को नहीं हटाते हैं जो वर्तमान निर्देशिका की उपनिर्देशिकाओं में रहती हैं।

यदि आप वर्तमान निर्देशिका के भीतर मौजूद सभी फ़ाइलों को हटाना चाहते हैं (जो कि उपनिर्देशिका में शामिल हैं, और उन उपनिर्देशिकाओं की उपनिर्देशिकाओं में, और इसके आगे - वर्तमान निर्देशिका या इसके किसी भी वंश में शामिल फाइलें), find बिना उपयोग करें maxdepth -1:

find . -not -name 'filename.gif' -name '*.gif' -delete

इससे सावधान रहें!

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

find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete

बस सुनिश्चित करें कि आपने -deleteपहले कभी नहीं डाला , दूसरे भावों से पहले! आप देखेंगे कि मैंने हमेशा -deleteअंत में रखा है । यदि आप इसे शुरुआत में डालते हैं, तो इसका मूल्यांकन पहले किया जाएगा, और सभी फाइलों के अंतर्गत .(जिसमें फाइलें समाप्त नहीं होती हैं .gifऔर गहरी उप-उप-फ़ाइलों में फाइलें शामिल हैं .) निर्देशिका को हटा दिया जाएगा!

अधिक जानकारी के लिए , के लिए मैनुअल पृष्ठों को देखने bashऔर shऔर इन उदाहरणों में इस्तेमाल किया आज्ञाओं के लिए: mv, rm, [, और (विशेष रूप से) find


1
धन्यवाद एलियाह। मैंने इसे आपके द्वारा सुझाए गए पहले तरीके के समान किया है, अर्थात् फाइल को एक अलग प्रारूप में बदलने और इसे वापस बदलने के लिए। लेकिन यह थोड़ा उप-इष्टतम और अशुद्ध लग रहा था। मुझे आपका दूसरा दृष्टिकोण पसंद आया है और @efthialex ने सुझाव दिया है और मैं अब इसका उपयोग कर रहा हूं। धन्यवाद!

1
@Marvis मुझे खुशी है कि यह आपकी जरूरतों को पूरा किया। वैसे, मैंने इस उत्तर को एक अन्य विधि (या विधियों के वर्ग) के उपयोग की जानकारी के साथ विस्तारित किया है find, जो अत्यधिक बहुमुखी है।
एलियाह कगन

3
विस्तृत उत्तर के लिए धन्यवाद findवास्तव में एक अच्छी खोज है।

1
कॉमन्सेंस के लिए +1 (मूव-डिलीट-मूव) उत्तर।
tu-Reinstate Monica-dor duh

Nit-pick: कैसे उनके findसाथ अजीब फाइलनेम को हैंडल *के लिए बेहतर है? लूप के लिए फ़ाइलों को *ठीक से संभालता है, क्योंकि आपने दोहरे उद्धरण चिह्नों का उपयोग किया है।
फ्लिम

28

यदि आप bash(डिफ़ॉल्ट शेल) का उपयोग कर रहे हैं , तो extglobशेल विकल्प आपको एक विस्तारित पैटर्न सिंटैक्स का उपयोग करने की अनुमति देता है। इसे सक्षम करने के लिए, shoptअंतर्निहित कमांड का उपयोग करें :

shopt -s extglob

(मैं उस लाइन को अपनी .bashrcफ़ाइल में शामिल करता हूँ ।)

अन्य बातों के अलावा, यह !()ऑपरेटर तक पहुंच प्रदान करता है , जो कि किसी भी पैटर्न से जुड़ा होता है, जो कि अंदर नहीं है। अपने उद्देश्य के लिए:

rm !(filename).gif

अधिक जानकारी man bash"पैटर्न मिलान" के तहत उपलब्ध है ।


1
बहुत बढ़िया जवाब! यह बैश-विशिष्ट है इसलिए यह पोर्टेबल स्क्रिप्टिंग के लिए उपयुक्त नहीं हो सकता है, लेकिन इंटरैक्टिव कार्यों और यहां तक ​​कि कुछ स्क्रिप्टिंग के लिए, यह जाने का सबसे अच्छा तरीका है। यह जोड़े गए जटिलता extglobको सक्षम करता है, लेकिन यदि यह अक्षम है तो कुछ भी बुरा नहीं होता है (उस स्थिति में, यह काम नहीं करता है)। और यह डिफ़ॉल्ट रूप से सक्षम होने लगता है, भले ही मेरे पास shopt -s extglobमेरी (या वैश्विक) कॉन्फ़िगरेशन फ़ाइलों में से कोई भी न हो । यदि यह मेरे लिए एक सरल स्पष्टीकरण है कि यह मेरे लिए बॉक्स से बाहर क्यों काम करता है, तो आप इसे इस उत्तर में जोड़ना चाह सकते हैं; या मैं एक नया प्रश्न पोस्ट कर सकता हूं।
एलियाह कगन

13

एक ओपन टर्मिनल के साथ Ctrl+ Alt+ Tऔर प्रकार:

find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;

के बीच का अंतर -deleteऔर -exec rm -vf {} \;है कि दूसरा विकल्प के साथ, आप की वजह से, फ़ाइलों को हटा दिया गया है जो देखने में सक्षम हो जाएगा -vझंडा। यह ऐसा कुछ है जो -deleteविकल्प के साथ नहीं किया जा सकता है । ( -name -deleteफ़ाइल नाम प्रिंट होगा, लेकिन rmसाथ -vका पता चलता है, तो प्रत्येक फ़ाइल था सफलतापूर्वक नष्ट कर दिया।)


1

नहीं है GLOBIGNOREचर। से man bash:

GLOBIGNORE
      A colon-separated list of patterns defining the set of filenames
      to be ignored by pathname expansion.  If a filename matched by a
      pathname expansion pattern also matches one of the  patterns  in
      GLOBIGNORE, it is removed from the list of matches.

तो, एक आसान तरीका यह GLOBGINOREहै कि सवाल में सिर्फ नाम निर्धारित किया जाए:

$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png

तो, आपके मामले में:

GLOBIGNORE=filename.gif; rm *.gif

बेशक, चूंकि GLOBIGNOREपैटर्न शामिल हैं, आप इसे तब भी उपयोग कर सकते हैं जब आप एक पैटर्न को बाहर करना चाहते हैं:

$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png

इसका एक फायदा (!) यहGLOBIGNORE है कि इसे... सेट करना स्वचालित रूप से बाहर हो जाता है और मिलान होने से, और यह सक्षम करता है dotglob:

The  GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern.  If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches.  The filenames ``.''  and ``..''  are  always  ignored
when  GLOBIGNORE is set and not null.  However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option,  so
all other filenames beginning with a ``.''  will match.  To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*''  one
of  the  patterns  in  GLOBIGNORE.  The dotglob option is disabled when
GLOBIGNORE is unset.

इसलिए, निर्देशिका में सभी फ़ाइलों और फ़ोल्डरों को हटाने का एक सरल तरीका :

GLOBIGNORE=.; rm -r *

*के साथ शुरुआत फ़ाइल नाम से मेल खाएगी .के बाद से, GLOBIGNOREसक्षम dotglobहै, लेकिन यह मेल नहीं खाएगा .या ..है, तो आप उस तरह से मूल निर्देशिका प्रभावित नहीं करेगा।

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