वर्तमान निर्देशिका की सभी फ़ाइलों का विस्तार से क्या वर्णन है?


92

मुझे पता **/*.extहै कि सभी उपनिर्देशिकाओं के मिलान में सभी फ़ाइलों का विस्तार होता है *.ext, लेकिन एक समान विस्तार क्या है जिसमें वर्तमान निर्देशिका में भी ऐसी सभी फाइलें शामिल हैं ?


4
मेरा बाश संभालती नहीं है **/*.ext। क्या आप सुनिश्चित हैं कि यह आपके लिए काम करता है?
tangens

@tangens आपको globstarडेनिस के उत्तर के अनुसार विकल्प को सक्षम करना है।
kenorb

जवाबों:


111

यह बाश 4 में काम करेगा:

ls -l {,**/}*.ext

काम करने के लिए डबल-तारांकन ग्लोब के लिए, globstarविकल्प को सेट करना होगा (डिफ़ॉल्ट: चालू):

shopt -s globstar

से man bash:

    globstar
                  यदि सेट किया जाता है, तो फ़ाइल नाम विस्तार शंकु में पैटर्न ** का उपयोग किया जाता है
                  पाठ एक फ़ाइल और शून्य या अधिक निर्देशिकाओं और से मेल खाएगा
                  उपनिर्देशिका। यदि पैटर्न का पालन किया जाता है a /, केवल
                  निर्देशिका और उपनिर्देशिका मेल खाते हैं।

अब मैं सोच रहा हूं कि ग्लोबस्टार प्रसंस्करण में एक बार बग हो सकता है, क्योंकि अब बस ls **/*.extमुझे सही परिणाम मिल रहा है।

भले ही, मैंने विश्लेषण पर ध्यान दिया किन्नोरब ने वीएलसी रिपॉजिटरी का उपयोग किया और उस विश्लेषण के साथ कुछ समस्याएं पाईं और मेरे उत्तर में तुरंत ऊपर:

findकमांड के आउटपुट की तुलना अमान्य है क्योंकि निर्दिष्ट करने -type fमें अन्य फ़ाइल प्रकार (विशेष रूप से निर्देशिका) और lsसंभावित रूप से सूचीबद्ध कमांड शामिल नहीं हैं। इसके अलावा, सूचीबद्ध कमांड्स में से एक, ls -1 {,**/}*.*- जो ऊपर दी गई खदान पर आधारित प्रतीत होगी, केवल उन नामों को आउटपुट करती है, जिनमें उन फ़ाइलों के लिए एक डॉट शामिल है जो उपनिर्देशिकाओं में हैं। ओपी के प्रश्न और मेरे उत्तर में एक बिंदु शामिल है क्योंकि जो मांगा जा रहा है वह एक विशिष्ट एक्सटेंशन वाली फाइल है।

हालांकि, सबसे महत्वपूर्ण बात यह है कि lsग्लोबस्टार पैटर्न के साथ कमांड का उपयोग करके एक विशेष मुद्दा है **। कई डुप्लिकेट उत्पन्न होते हैं क्योंकि पैटर्न को बैश द्वारा पेड़ में सभी फ़ाइल नाम (और निर्देशिका नाम) की जांच की जाती है। यदि वे निर्देशिका हैं, तो विस्तार के बाद lsकमांड उनमें से प्रत्येक और उनकी सामग्री को सूचीबद्ध करता है ।

उदाहरण:

हमारी वर्तमान निर्देशिका में उपनिर्देशिका Aऔर इसकी सामग्री है:

A
└── AB
    └── ABC
        ├── ABC1
        ├── ABC2
        └── ABCD
            └── ABCD1

उस पेड़ में, **"AA / AB A / AB / ABC A / AB / ABC / ABC1 A / AB / ABC / ABC2 A / AB / ABC / ABCD / AB / ABC / ABCD1" (7 प्रविष्टियाँ) का विस्तार होता है । यदि आप ऐसा करते हैं तो आपको echo **सटीक आउटपुट मिलेगा और प्रत्येक प्रविष्टि को एक बार दर्शाया जाएगा। हालाँकि , यदि आप ऐसा करते हैं तो उन प्रविष्टियों में ls **से प्रत्येक की एक सूची को आउटपुट करने जा रहा है । इसलिए अनिवार्य रूप से इसका ls Aपालन ​​किया जाता है ls A/AB, आदि, इसलिए A/ABदो बार दिखाया जाता है। इसके अलावा, lsप्रत्येक उपनिर्देशिका के आउटपुट को अलग करने जा रहा है:

...
<blank line>
directory name:
content-item
content-item

इसलिए wc -lउन सभी रिक्त लाइनों और निर्देशिका नाम अनुभाग शीर्षकों का उपयोग करते हुए, जो गिनती को दूर तक फेंकता है।

यह एक और कारण है कि आपको पार्सls क्यों नहीं करना चाहिए ।

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

for entry in **
do
    something "$entry"
done

अंतिम तुलना के रूप में, मैंने एक बैश स्रोत भंडार का उपयोग किया था जो मैंने काम किया था और यह किया:

shopt -s globstar dotglob
diff <(echo ** | tr ' ' '\n') <(find . | sed 's|\./||' | sort)
0a1
> .

मैं trरिक्त स्थान को नई-नई सूची में बदलता था जो केवल यहाँ मान्य है क्योंकि कोई भी नाम रिक्त स्थान शामिल नहीं करता है। मैं आउटपुट की प्रत्येक पंक्ति से sedअग्रणी को निकालता ./था find। मैंने इसका आउटपुट सॉर्ट किया findक्योंकि यह सामान्य रूप से अनसोल्ड है और बैश का ग्लब्स का विस्तार पहले से ही सॉर्ट है। जैसा कि आप देख सकते हैं, से केवल उत्पादन diffवर्तमान निर्देशिका .आउटपुट था find। जब मैंने किया ls ** | wc -lतो आउटपुट में लगभग दो बार कई लाइनें थीं।


5
मैंने उबंटू और साइगविन का परीक्षण किया, और globstarडिफ़ॉल्ट रूप सेoff
स्टीवन पेनी

12
सबसे अच्छा जवाब! लेकिन मुझे लगता है कि **/*.extहालांकि पर्याप्त होना चाहिए। इसके अलावा, आपके पास छिपी हुई फाइलें नहीं होंगी जब तक कि आप नहीं shopt -s dotglob
गनीउर्फ़_ग्निउरफ़

2
अक्षम करने के लिए globstar: shopt -u globstar
केनोरब

4
@gniourf_gniourf सवाल वास्तव में वर्तमान निर्देशिका को विशेष रूप से शामिल करने के लिए कहता है, **/*.extपर्याप्त नहीं होगा
msciwoj

2
@dotnetCarpenter: MacOS के साथ बश का संस्करण 3.2 है जो ग्लोबस्टार का समर्थन नहीं करता है, जैसा कि आपको पता चला है। एक डबल तारांकन एकल के रूप में एक ही माना जाता है। ग्लोबस्टार को बाश 4.0 में पेश किया गया था।
अगली सूचना तक रोक दिया गया।

13

यह wil वर्तमान निर्देशिका और इसके उपनिर्देशिकाओं की सभी फाइलों को प्रिंट करता है जो '.ext' में समाप्त होती हैं।

find . -name '*.ext' -print

हालांकि यह उत्तर ओपी के अनुरोध को "विस्तार" से पूरी तरह से पूरा नहीं करता है, यह वांछित परिणाम उत्पन्न करने की सबसे अधिक संभावना है।
अगली सूचना तक रोक दिया गया।

7

आप का उपयोग कर सकते हैं: **/*.*सभी फ़ाइलों को पुनरावर्ती रूप से शामिल करने के लिए (द्वारा सक्षम करें shopt -s globstar)।

कृपया अन्य विविधताओं के परीक्षण के बारे में जानें और वे कैसे व्यवहार करते हैं।


नमूना VLC रिपॉजिटरी फ़ोल्डर में 3472 फ़ाइलों के साथ परीक्षण फ़ोल्डर:

(कुल 3472 प्रति के रूप में गिना की फाइलें: find . -type f | wc -l)

  • ls -1 **/*.* - रिटर्न 3338
  • ls -1 {,**/}*.*- रिटर्न 3341 ( डेनिस द्वारा प्रस्तावित )
  • ls -1 {,**/}* - 8265 लौटाता है
  • ls -1 **/*- छिपी हुई फाइलों को छोड़कर, रिटर्न 7817 ( डेनिस द्वारा प्रस्तावित )
  • ls -1 **/{.[^.],}*- रिटर्न 7869 ( डेनिस द्वारा प्रस्तावित )
  • ls -1 {,**/}.?* - रिटर्न 15855
  • ls -1 {,**/}.* - 20321 लौटाता है

इसलिए मुझे लगता है कि सभी फ़ाइलों को पुनरावर्ती रूप से सूचीबद्ध करने के लिए सबसे निकटतम विधि पहला उदाहरण है ( **/*.*) gniourf-gniourf टिप्पणी के अनुसार (फाइलों का उचित एक्सटेंशन है, या विशिष्ट का उपयोग करें), जैसा कि दूसरा उदाहरण नीचे कुछ और विवरण देता है :

$ diff -u <(ls -1 {,**/}*.*) <(ls -1 **/*.*)
--- /dev/fd/63  2015-04-19 15:25:07.000000000 +0100
+++ /dev/fd/62  2015-04-19 15:25:07.000000000 +0100
@@ -1,6 +1,4 @@
 COPYING.LIB
-COPYING.LIB
-Makefile.am
 Makefile.am
@@ -45,7 +43,6 @@
 compat/tdestroy.c
 compat/vasprintf.c
 configure.ac
-configure.ac

और दूसरा और भी डुप्लिकेट उत्पन्न करता है।


छिपी हुई फ़ाइलों को शामिल करने के लिए, का उपयोग करें: shopt -s dotglob(द्वारा अक्षम shopt -u dotglob)। यह अनुशंसित नहीं है, क्योंकि यह कमांड को प्रभावित कर सकता है जैसे कि mvया rmआप गलती से गलत फ़ाइलों को हटा सकते हैं।


ग्लोबस्टार सक्षम के साथ मैक टर्मिनल और बैश पर, मैंने उपरोक्त समाधान ( **/*.*) जानकारीपूर्ण पाया और सबसे अच्छा काम किया। स्वीकृत उत्तर ने शीर्ष निर्देशिका में आइटम के डुप्लिकेट का कारण बना। मेरा काम करने का पैटर्न था:"${path}"**/*.*
मम्बोट

यह अन्य विकल्पों जैसे nullglob और dotglob
Wilf

4
$ find . -type f

वह वर्तमान निर्देशिका की सभी फाइलों को सूचीबद्ध करेगा। आप -exec का उपयोग करके आउटपुट पर कुछ अन्य कमांड कर सकते हैं

$find . -type f -exec grep "foo" {} \;

यह स्ट्रिंग "फू" के लिए खोज से प्रत्येक फ़ाइल को grep करेगा।


अब जब यह 11 साल बाद है, तो समय हो सकता है कि कोई व्यक्ति find . -type fवर्तमान निर्देशिका में रूट के साथ पुनरावर्ती रूप से लागू होता है, न केवल वर्तमान निर्देशिका के लिए।
रोजर डाहल

4

वर्तमान निर्देशिका को शामिल करने के लिए ब्रेस विस्तार का उपयोग क्यों न करें?

./{*,**/*}.ext

ब्रेस का विस्तार ग्लोब विस्तार से पहले होता है, इसलिए आप प्रभावी रूप से बैश के पुराने संस्करणों के साथ क्या कर सकते हैं, और नए संस्करणों में ग्लोबस्टार के साथ बंदर करना कर सकते हैं।

इसके अलावा, यह ./आपके ग्लोब पैटर्न में अग्रणी को शामिल करने के लिए बैश में अच्छा अभ्यास माना जाता है ।

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