जवाबों:
बैश में आप यह सक्षम करने से क्या कर सकते हैं extglobइस तरह, विकल्प (की जगह lsके साथ cpऔर लक्ष्य निर्देशिका जोड़ने के लिए, निश्चित रूप से)
~/foobar> shopt extglob
extglob off
~/foobar> ls
abar afoo bbar bfoo
~/foobar> ls !(b*)
-bash: !: event not found
~/foobar> shopt -s extglob # Enables extglob
~/foobar> ls !(b*)
abar afoo
~/foobar> ls !(a*)
bbar bfoo
~/foobar> ls !(*foo)
abar bbar
आप बाद में extglob को अक्षम कर सकते हैं
shopt -u extglob
f, को छोड़कर, के साथ शुरू होगा foo?
extglobखोल विकल्प आपको कमांड लाइन में और अधिक शक्तिशाली पैटर्न मिलान देता है।
आप इसे चालू करते हैं shopt -s extglob, और इसे बंद कर देते हैं shopt -u extglob।
अपने उदाहरण में, आप शुरू में करेंगे:
$ shopt -s extglob
$ cp !(*Music*) /target_directory
पूर्ण उपलब्ध ext समाप्त ग्लोब बिंग ऑपरेटर हैं (इससे अंश man bash):
यदि एक्सग्लोब शेल विकल्प को शॉप बिलिन का उपयोग करने में सक्षम किया जाता है, तो कई विस्तारित पैटर्न मिलान ऑपरेटरों को मान्यता दी जाती है। एक पैटर्न-सूची एक या एक से अलग पैटर्न की एक सूची है a | निम्नलिखित उप-पैटर्नों में से एक या अधिक का उपयोग करके समग्र पैटर्न बनाया जा सकता है:
- ? (पैटर्न-सूची)
दिए गए पैटर्न के शून्य या एक घटना से मेल खाती है- * (पैटर्न-सूची)
दिए गए पैटर्न के शून्य या अधिक घटनाओं से मेल खाता है- + (पैटर्न-सूची)
दिए गए पैटर्न की एक या अधिक घटनाओं से मेल खाता है- @ (पैटर्न-सूची)
किसी दिए गए पैटर्न से मेल खाती है- ! (पैटर्न-सूची)
दिए गए पैटर्न में से एक को छोड़कर किसी भी चीज से मेल खाता है
इसलिए, उदाहरण के लिए, यदि आप वर्तमान निर्देशिका में उन सभी फाइलों को सूचीबद्ध करना चाहते हैं जो फाइलें .cया नहीं हैं .h, तो आप ऐसा करेंगे:
$ ls -d !(*@(.c|.h))
बेशक, सामान्य शेल ग्लोबिंग कार्य करता है, इसलिए अंतिम उदाहरण के रूप में भी लिखा जा सकता है:
$ ls -d !(*.[ch])
.cया .hफ़ाइलें एक निर्देशिका है।
D, लेकिन उपनिर्देशिका की सामग्री नहीं जो निर्देशिका में निहित हो सकती है D।
बाश में नहीं (कि मुझे पता है), लेकिन:
cp `ls | grep -v Music` /target_directory
मुझे पता है कि यह वही नहीं है जो आप ढूंढ रहे थे, बल्कि यह आपके उदाहरण को हल करेगा।
यदि आप निष्पादन कमांड का उपयोग करने की लागत से बचना चाहते हैं, तो मेरा मानना है कि आप xargs के साथ बेहतर कर सकते हैं। मुझे लगता है कि निम्नलिखित एक अधिक कुशल विकल्प है
find foo -type f ! -name '*Music*' -exec cp {} bar \; # new proc for each exec
find . -maxdepth 1 -name '*Music*' -prune -o -print0 | xargs -0 -i cp {} dest/
बैश में, वैरिएबलshopt -s extglob का एक विकल्प है । यह वास्तव में बेहतर नहीं है, लेकिन मुझे याद रखना आसान है।GLOBIGNORE
एक उदाहरण जो मूल पोस्टर चाहता था वह हो सकता है:
GLOBIGNORE="*techno*"; cp *Music* /only_good_music/
जब किया, स्रोत निर्देशिका में unset GLOBIGNOREसक्षम होने के लिए rm *techno*।
तुम भी एक बहुत ही सरल उपयोग कर सकते हैं for लूप का :
for f in `find . -not -name "*Music*"`
do
cp $f /target/dir
done
-maxdepth 1गैर-पुनरावर्ती के लिए उपयोग करें ?
findयदि किसी भी nontrivial फ़ाइल नामों को ढूंढता है तो बैकटिक्स का उपयोग अप्रिय तरीकों से टूट जाएगा।
मेरी व्यक्तिगत प्राथमिकता grep और जबकि कमांड का उपयोग करना है। यह एक शक्तिशाली अभी तक पठनीय स्क्रिप्ट लिखने के लिए अनुमति देता है यह सुनिश्चित करता है कि आप अंत में वही करना चाहते हैं जो आप चाहते हैं। इसके अलावा एक गूंज कमांड का उपयोग करके आप वास्तविक ऑपरेशन को अंजाम देने से पहले सूखा रन कर सकते हैं। उदाहरण के लिए:
ls | grep -v "Music" | while read filename
do
echo $filename
done
उन फ़ाइलों का प्रिंट आउट लेगा जिन्हें आप कॉपी करेंगे। यदि सूची सही है, तो अगला चरण कॉपी कमांड के साथ इको कमांड को बस इस प्रकार बदलना है:
ls | grep -v "Music" | while read filename
do
cp "$filename" /target_directory
done
bashआप का उपयोग कर सकते हैं while IFS='' read -r filename, लेकिन तब newlines अभी भी एक समस्या है। सामान्य रूप lsसे फ़ाइलों को एन्यूमरेट करने के लिए उपयोग नहीं करना सबसे अच्छा है ; जैसे उपकरण findबहुत बेहतर अनुकूल हैं।
for file in *; do case ${file} in (*Music*) ;; (*) cp "${file}" /target_directory ; echo ;; esac; done
एक चाल मैं यहाँ पर अभी तक नहीं देखा है कि उपयोग नहीं करता है extglob, findया grepसेट के रूप में दो फ़ाइल सूचियों और इलाज के लिए है "diff" उन्हें प्रयोग comm:
comm -23 <(ls) <(ls *Music*)
commपर अधिक बेहतर है diffक्योंकि इसमें अतिरिक्त क्रॉफ्ट नहीं है।
यह रिटर्न सेट 1 के सभी तत्वों, ls, कि कर रहे हैं नहीं सेट 2 में भी ls *Music*। इसके लिए दोनों सेटों को ठीक से काम करने के लिए क्रमबद्ध क्रम में होना आवश्यक है। lsऔर ग्लोब विस्तार के लिए कोई समस्या नहीं है , लेकिन अगर आप कुछ का उपयोग कर रहे हैं find, तो सुनिश्चित करें sort।
comm -23 <(find . | sort) <(find . | grep -i '.jpg' | sort)
संभावित रूप से उपयोगी।
comm -23 <(ls) exclude_these.list
इसके लिए एक समाधान खोजा जा सकता है।
$ mkdir foo bar
$ touch foo/a.txt foo/Music.txt
$ find foo -type f ! -name '*Music*' -exec cp {} bar \;
$ ls bar
a.txt
ढूँढें के पास कुछ विकल्प हैं, आप जो कुछ भी शामिल करते हैं और बाहर करते हैं, उस पर बहुत विशिष्ट प्राप्त कर सकते हैं।
संपादित करें: टिप्पणियों में एडम ने कहा कि यह पुनरावर्ती है। इसके विकल्प को खोजने के लिए माइंडपीथ और मैक्सडेपथ उपयोगी हो सकते हैं।
find -maxdepth 1 -not -name '*Music*'/ target_directory
निम्नलिखित कार्य सभी को सूचीबद्ध करता है *.txt वर्तमान डीआईआर में फाइलों को , सिवाय उनके जो एक संख्या से शुरू होते हैं।
इस में काम करता है bash, dash, zshऔर अन्य सभी POSIX संगत गोले।
for FILE in /some/dir/*.txt; do # for each *.txt file
case "${FILE##*/}" in # if file basename...
[0-9]*) continue ;; # starts with digit: skip
esac
## otherwise, do stuff with $FILE here
done
एक पंक्ति में पैटर्न /some/dir/*.txtउन forसभी फाइलों पर लूप को पुनरावृत्त करने का कारण होगा /some/dirजिनके नाम के साथ समाप्त होता है.txt ।
लाइन टू में एक केस स्टेटमेंट का उपयोग अवांछित फ़ाइलों को हटाने के लिए किया जाता है। - ${FILE##*/}अभिव्यक्ति फ़ाइल नाम (यहां /some/dir/) से किसी भी प्रमुख dir नाम घटक को बंद कर देती है ताकि पेटेंट फ़ाइल के केवल आधार के खिलाफ मेल कर सकें। (यदि आप केवल प्रत्ययों के आधार पर फ़ाइल नाम का निराकरण कर रहे हैं, तो आप इसे छोटा कर सकते हैं$FILE इसके बजाय ।)
पंक्ति तीन में, caseपैटर्न से मेल खाने वाली सभी फाइलें [0-9]*छोड़ दी जाएंगी ( continueकथन forलूप के अगले पुनरावृत्ति पर कूद जाता है )। - यदि आप चाहते हैं कि आप यहाँ कुछ और दिलचस्प कर सकें, जैसे कि सभी फ़ाइलों को छोड़ देना, जो एक अक्षर (a-z) के साथ शुरू नहीं होती है [!a-z]*, या आप कई प्रकार के फ़ाइल नाम को छोड़ने के लिए कई पैटर्न का उपयोग कर सकते हैं जैसे [0-9]*|*.bakकि दोनों .bakफ़ाइलों को छोड़ना , और फाइलें जो एक नंबर से शुरू नहीं होती हैं।
*.txtसिर्फ के बजाय के खिलाफ मिलान *)। अब तय हो गया।
यह वास्तव में 'संगीत' को छोड़कर होगा
cp -a ^'Music' /target
यह और कि संगीत जैसी चीजों को छोड़कर? * या *? संगीत
cp -a ^\*?'complete' /target
cp -a ^'complete'?\* /target
cpMacOS पर मैन्युअल पृष्ठ एक है -aविकल्प है, लेकिन यह कुछ पूरी तरह से अलग करता है। कौन सा मंच इसका समर्थन करता है?
ls /dir/*/!(base*)