एक विशिष्ट एक्सटेंशन के साथ फ़ाइलों की पुन: खोज करें


437

मैं एक निर्देशिका में एक विशिष्ट विस्तार के साथ सभी फाइलों को खोजने की कोशिश कर रहा हूं और इसकी उपनिर्देशिकाएं मेरे बैश (नवीनतम उबंटू एलटीएस रिलीज) के साथ।

यह एक स्क्रिप्ट फ़ाइल में लिखा है:

#!/bin/bash

directory="/home/flip/Desktop"
suffix="in"

browsefolders ()
  for i in "$1"/*; 
  do
    echo "dir :$directory"
    echo "filename: $i"
    #   echo ${i#*.}
    extension=`echo "$i" | cut -d'.' -f2`
    echo "Erweiterung $extension"
    if     [ -f "$i" ]; then        

        if [ $extension == $suffix ]; then
            echo "$i ends with $in"

        else
            echo "$i does NOT end with $in"
        fi
    elif [ -d "$i" ]; then  
    browsefolders "$i"
    fi
  done
}
browsefolders  "$directory"

दुर्भाग्य से, जब मैं इस स्क्रिप्ट को टर्मिनल में शुरू करता हूं, तो यह कहता है:

[: 29: in: unexpected operator

(के $extensionबजाय 'in')

यहाँ क्या हो रहा है, त्रुटि कहाँ है? लेकिन यह घुंघराले ब्रेस


2
त्रुटि एक लापता '{' से है
shrewmouse

जवाबों:


750
find $directory -type f -name "*.in"

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

आपकी स्क्रिप्ट संभवतः उन प्रविष्टियों के लिए विफल हो रही .है जिनके नाम में ए नहीं है , $extensionखाली कर रहे हैं।


16
हां, findडिफ़ॉल्ट रूप से पुनरावर्ती है। यदि आप चाहें तो गहराई को सीमित कर सकते हैं (मैन पेज देखें)।
चटाई

1
मैं सभी फाइलों को एक जार-फाइल के तर्क के रूप में पास करना चाहता हूं। यह कैसे किया जा सकता है?
फ्लिप

8
@flip: यह एक अलग सवाल है। एक नया प्रश्न पोस्ट करें, जो आप करना चाहते हैं और जो आपने अब तक आज़माया है, उसका विवरण दें।
चटाई

एक छोटा सुधार: "* .in" के बजाय '* .in' या \ * का उपयोग करें क्योंकि दोहरे उद्धरण शेल विस्तार को रोकते नहीं हैं। यानी आपकी स्क्रिप्ट ठीक से काम नहीं करेगी अगर वर्तमान निर्देशिका में .in एक्सटेंशन के साथ एक फ़ाइल है।
शनात्सेल

4
@Shanatsel: दोहरे उद्धरण शेल विस्तार को रोकते हैं। कोशिश करके देखो।
Mat

188
find {directory} -type f -name '*.extension'

उदाहरण:csv वर्तमान निर्देशिका और इसके उप-निर्देशिकाओं में सभी फ़ाइलों को खोजने के लिए , उपयोग करें:

find . -type f -name '*.csv'

60

मेरे द्वारा उपयोग किए गए सिंटैक्स की तुलना में थोड़ा भिन्न है

find $directory -type f -name \*.in

(यह एक कम कीस्ट्रोक है)।


1
मैट की स्क्रिप्ट भी काम नहीं करेगी यदि वर्तमान निर्देशिका में .in एक्सटेंशन के साथ एक फ़ाइल है, जबकि आपका अभी भी काम करेगा। देखें stackoverflow.com/questions/5927369/...
Shnatsel

4
@Shnatsel इस टिप्पणी (और इसलिए तुम्हारा) सादा गलत है।
ग्नौरफ_ग्निउरफ

1
@gniourf_gniourf आपको अपने बयान के लिए कुछ संदर्भ प्रदान करना चाहिए, अन्यथा कोई केवल यह तर्क दे सकता है: "नहीं, आप गलत हैं"। लेकिन वास्तव में आप सही हैं: gnu.org/software/bash/manual/html_node/Double-Quotes.html
Murmel

@ user1885518: मुझे लगता है कि यह वह व्यक्ति होना चाहिए जो यह दावा करता है कि स्क्रिप्ट काम नहीं करती है जो स्क्रिप्ट को विफल होने पर कुछ उदाहरण प्रदान करना चाहिए। जब मैं टूटी हुई स्क्रिप्टों को छोड़ता हूं तो यही करता हूं: यह आमतौर पर रिक्त स्थान, न्यूलाइन्स, ग्लब्स इत्यादि वाले उद्धरणों और फाइलनामों के बारे में है, और मैं विशेष रूप से समझाता हूं कि यह क्यों टूटा है।
गनीउर्फ_ग्निउरफ

2
संदर्भ प्रदान करना हमेशा चर्चा में एक अच्छा तरीका होता है, यह इस बात पर निर्भर नहीं करता है कि पहले कौन था। वह चाहिए, आपको चाहिए।
मुरली

14

उपयोग किए बिना find:

du -a $directory | awk '{print $2}' | grep '\.in$'

3
grepयहाँ वास्तव में आवश्यक नहीं है। awkनियमित अभिव्यक्ति है और एक पैटर्न से मेल खाने वाले मूल्यों तक इसके उत्पादन को सीमित कर सकता है।
केनस्टर

अगर आप 100 टेराबाइट से गुजर रहे हैं तो यह तरीका बेहद उपयोगी है। ढूँढें कमांड को प्रोसेस करने में बहुत अधिक समय लगता है। यह तुरंत शुरू होता है।
प्रोटोनोवा

1
awk|grepएक विरोधी पैटर्न है। जाग्रत करते हैं।
जेन्स

10
  1. के {बाद एक लापता हैbrowsefolders ()
  2. सब $inहोना चाहिए$suffix
  3. के साथ की रेखा cutआपको केवल मध्य भाग के लिए मिलती है front.middle.extension। आपको अपने शेल मैनुअल को अपने ${varname%%pattern}मित्रों और मित्रों को पढ़ना चाहिए ।

मुझे लगता है कि आप इसे शेल स्क्रिप्टिंग में एक अभ्यास के रूप में करते हैं, अन्यथा find पहले से प्रस्तावित समाधान जाने का रास्ता है।

एक स्क्रिप्ट चलाने के बिना, उचित शेल सिंटैक्स की जांच करने के लिए, उपयोग करें sh -n scriptname



7

हालांकि findकमांड का उपयोग करना यहां उपयोगी हो सकता है, शेल खुद को बिना किसी तीसरे पक्ष के उपकरण के इस आवश्यकता को प्राप्त करने के लिए विकल्प प्रदान करता है। bashखोल जो आप पुनरावर्ती पथ के तहत फ़ाइल नाम प्राप्त कर सकते हैं का उपयोग कर एक विस्तारित ग्लोब समर्थन विकल्प प्रदान करता है कि एक्सटेंशन आप चाहते हैं के साथ मैच।

विस्तारित विकल्प extglobजो shoptनीचे दिए गए विकल्प का उपयोग करके सेट किया जाना है । विकल्प -sसमर्थन के साथ सक्षम हैं और वह -uध्वज के साथ अक्षम है । इसके अतिरिक्त आप कुछ और विकल्पों का उपयोग कर सकते हैं nullglobजिनमें एक बेजोड़ गोला पूरी तरह से बह गया है, जिसे शून्य शब्दों के एक सेट के साथ बदल दिया गया है। और globstarवह सभी निर्देशिकाओं के माध्यम से पुनरावृत्ति करने की अनुमति देता है

shopt -s extglob nullglob globstar

अब आपको बस इतना करना है कि एक निश्चित एक्सटेंशन की फाइलों को शामिल करने के लिए ग्लोब एक्सप्रेशन बनाएं जो आप नीचे बता सकते हैं। हम ग्लोब परिणामों को पॉप्युलेट करने के लिए एक सरणी का उपयोग करते हैं क्योंकि जब ठीक से उद्धृत और विस्तारित किया जाता है, तो विशेष वर्ण वाले फ़ाइल नाम बरकरार रहेंगे और शेल द्वारा शब्द-विभाजन के कारण टूट नहीं जाएंगे।

उदाहरण के लिए *.csvपुनरावर्ती रास्तों की सभी फाइलों को सूचीबद्ध करना

fileList=(**/*.csv)

विकल्प **उप-फ़ोल्डरों के माध्यम से पुनरावृत्ति करना है और *.csvउल्लिखित एक्सटेंशन की किसी भी फ़ाइल को शामिल करने के लिए ग्लोब विस्तार है। अब वास्तविक फाइलों की छपाई के लिए, बस

printf '%s\n' "${fileList[@]}"

एक सरणी का उपयोग करना और एक उचित उद्धृत विस्तार करना, शेल स्क्रिप्ट में उपयोग किए जाने का सही तरीका है, लेकिन इंटरेक्टिव उपयोग के लिए, आप बस lsग्लोब अभिव्यक्ति के साथ उपयोग कर सकते हैं

ls -1 -- **/*.csv

यह बहुत अच्छी तरह से कई फ़ाइलों से मेल खाने के लिए विस्तारित किया जा सकता है यानी फ़ाइल कई एक्सटेंशन के साथ समाप्त होती है (यानी findकमांड में कई झंडे जोड़ने के समान )। उदाहरण के लिए सभी पुनरावर्ती छवि फ़ाइलों को प्राप्त करने की आवश्यकता के एक मामले पर विचार करें *.gif, अर्थात एक्सटेंशन , *.pngऔर *.jpg, आपको बस इतना करना होगा

ls -1 -- **/+(*.jpg|*.gif|*.png)

यह बहुत अच्छी तरह से विस्तारित किया जा सकता है नकारात्मक परिणाम भी है। एक ही वाक्य रचना के साथ, कोई निश्चित प्रकार की फ़ाइलों को बाहर करने के लिए ग्लोब के परिणामों का उपयोग कर सकता है। मान लें कि आप ऊपर के एक्सटेंशन वाले फ़ाइल नामों को बाहर करना चाहते हैं, तो आप कर सकते हैं

excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"

निर्माण !()एक नकारात्मक ऑपरेशन है, जिसमें किसी भी फ़ाइल एक्सटेंशन को सूचीबद्ध नहीं किया गया है और |यह एक अल्टरनेशन ऑपरेटर है, जिसका उपयोग ग्लोब के OR मैच करने के लिए एक्सटेंडेड रेगुलर एक्सप्रेशंस लाइब्रेरी में किया जाता है।

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


6

pom.xmlअपनी वर्तमान निर्देशिका की सभी फ़ाइलों को खोजने और उन्हें प्रिंट करने के लिए, आप इसका उपयोग कर सकते हैं:

find . -name 'pom.xml' -print


0
for file in "${LOCATION_VAR}"/*.zip
do
  echo "$file"
done 

1
हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन यह कोड क्यों और / या इस प्रश्न के उत्तर के बारे में अतिरिक्त संदर्भ प्रदान करता है, इसके दीर्घकालिक मूल्य में सुधार करता है।
रोलस्टूफ़्लोरहेयर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.