कमांड लाइन में * से बाहर निकालें


14

ऐसी बहुत सी परिस्थितियाँ हैं जहाँ एक का उपयोग *वास्तव में अपरिहार्य है - उदाहरण rm -rf *के लिए एक फ़ोल्डर में जो हजारों सबफ़ोल्डर्स और फ़ाइलों को रखता है।

लेकिन क्या होगा अगर आप rmकमांड से सिर्फ एक या दो फाइल या फ़ोल्डर्स को बाहर करना चाहते हैं ? मैंने अपना रास्ता इधर-उधर कर लिया है और केवल काफी जटिल समाधान ढूंढे हैं जैसे find . -depth -not \( -name 'one' -o -name 'two' \ -o -name 'three' \) -exec rm {} \;कि यहाँ बताया गया है

क्या यह एक आसान तरीके से करने की संभावना है - बिना इस चक्कर के find? जैसे rm -rf --exclude='one' --exclude='two' --exclude='three' *rsync में या बस rm -rf -e 'one','two','three' *?

हो सकता है कि यहां तक कि एक सामान्य संभावना से बातें बाहर करने के लिए *(ताकि अन्य आदेशों की तरह cp, mv... अपने स्वयं के लागू करने के लिए नहीं है)? कुछ ऐसा है *{'one','two','three'}या ऐसा है?


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

यह एक संभावना होगी, लेकिन यह लगभग उतना ही विस्तृत है जितना कि मैंने उल्लेख किया है। मुझे पता है कि मैं कमांड्स को कुछ इस तरह से जोड़ सकता हूं mv -t /tmp one two three && rm -rf * && mv -t . /tmp/one /tmp/two /tmp/three, लेकिन मैं एक ऐसा समाधान देना पसंद करूंगा, जिसमें किसी चीज को आसानी से बाहर निकालने की संभावना हो *। निश्चित रूप से ऐसी स्थितियां होंगी जहां फ़ाइलों को किसी अन्य गंतव्य पर ले जाना या कॉपी करना एक विकल्प नहीं होगा।
डेविड

2
यह है, यही वजह है कि मैंने इसे उत्तर के रूप में पोस्ट नहीं किया। चीजों को करने के एक कम जटिल तरीके के रूप में विलय करें (तीन बहुत सरल आदेश बनाम एक और अधिक जटिल वाले)। मैं rm के साथ संयोजन में जटिलता से नफरत करता हूं।
हेन्स

जवाबों:


33

बैश के लिए एक खोल विकल्प कहा जाता है extglobजाता है कि डिफ़ॉल्ट रूप से निष्क्रिय मानक खोल वाक्य रचना के साथ संगतता रखने के लिए। Extglob जैसे अतिरिक्त ऑपरेटरों द्वारा वाक्य रचना का पूरक है !(), ?(), @()और कुछ और।

स्विच करने के लिए extglob, टाइप करें shopt -s extglob। चालू उपयोगकर्ता प्रकार के लिए इसे चालू रखने के लिए echo 'shopt -s extglob' >> ~/.bashrc

Rm उदाहरण के लिए: extglobआप उपयोग कर सकते हैं

rm -rf !(one|two|three)

एक अच्छे समाधान की तरह लगता है, लेकिन मैं यह भी बंद नहीं करना चाहता कि हर बार जब मैं वर्णित स्थिति की तरह एक स्थिति में आता हूं।
डेविड

3
@ दाविद: आप shoptअपनी बात रख ~/.bashrcसकते हैं, यह चोट नहीं पहुँचा सकता।
enzotib

अगर मुझे यह सही लगता है, तो एक्सग्लोब ऑप्शन का प्रभाव बिल्कुल भी नहीं बदलता है *, बल्कि इसके !अतिरिक्त संकेतक (जैसे ) अतिरिक्त कार्य करता है? उस मामले में यह एक सुंदर समाधान होगा।
डेविड

1
@ डेविड: बिल्कुल।
चोरोबा

1
@ मानक शेल सिंटैक्स के साथ संगतता बनाए रखने के लिए । ऐसी अन्य परिस्थितियाँ हैं जहाँ व्यवहार में बदलाव हो सकता है।
gerrit

4

मैंने बिलकुल इसके अलावा बनाया है (sry कि मैं अभी तक दस्तावेज़ जोड़ने में सक्षम नहीं था)।

मेरे पास निम्नलिखित की तरह एक फ़ोल्डर है:

$ ls
a b c d

टाइपिंग except b dआपको aऔर देगाc

$ except b d
ac

अब आप इसे पाइप कर सकते हैं rm

except b d | xargs -0 rm

यह याद रखना कठिन हो सकता है, इसलिए सिर्फ एक स्क्रिप्ट को छोड़कर, शीर्ष पर क्यों नहीं बनाया जाना चाहिए rm-except:

#!/usr/bin/env bash

except "$@" | xargs -0 rm

इसी तरह आसान है ls-except:

#!/usr/bin/env bash

except "$@" | xargs -0 ls

3
यह अच्छा है, लेकिन वास्तव में ज़रूरत नहीं है जब आप एक्सग्लोब के बारे में जानते हैं - askubuntu.com/a/329233/138369
डेविड

1

एक्सग्लोब के विकल्प के रूप में (हालांकि यह बहुत अच्छा जवाब है और सभी को shopt -s extglob globstarअपने .bashrc में होना चाहिए ), आप $ GLOBIGNORE वैश्विक चर का उपयोग कर सकते हैं । मान लें कि आप 'foo.txt' और 'bar baz.txt' को छोड़कर हर फ़ाइल प्राप्त करना चाहते हैं:

GLOBIGNORE=foo.txt:'bar baz.txt'

... हालाँकि, यह शेल विकल्प को चालू कर देगा dotglob, जिसका अर्थ है कि *एक डॉट के साथ शुरू होने वाली फ़ाइलों से मेल खाएगा (जो सामान्य रूप से छिपे हुए हैं)। तो आपको वास्तव में दो आदेशों की आवश्यकता है:

GLOBIGNORE=foo.txt:'bar baz.txt'
shopt -u dotglob

चूँकि यह एक वैश्विक चर है, इसलिए यह आपके द्वारा उपयोग किए जाने वाले हर ग्लोब को तब तक प्रभावित करेगा जब तक $ GLOBSTAR या तो लॉग आउट करके या साथ में परेशान न हो

GLOBIGNORE=

यह केवल चर के लिए पारित शाब्दिक तार पर भी काम करेगा। आप देख सकते हैं कि $ GLOBIGNORE सेट करके और इन कमांडों के बीच के अंतर को देखकर मेरा क्या मतलब है:

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