जवाबों:
बैश में आप यह सक्षम करने से क्या कर सकते हैं 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
cp
MacOS पर मैन्युअल पृष्ठ एक है -a
विकल्प है, लेकिन यह कुछ पूरी तरह से अलग करता है। कौन सा मंच इसका समर्थन करता है?
ls /dir/*/!(base*)