एक विशिष्ट एक्सटेंशन के साथ सभी फ़ाइलों के माध्यम से लूप


109
for i in $(ls);do
    if [ $i = '*.java' ];then
        echo "I do something with the file $i"
    fi
done

मैं वर्तमान फ़ोल्डर में प्रत्येक फ़ाइल के माध्यम से लूप करना चाहता हूं और यह जांचता हूं कि क्या यह किसी विशिष्ट एक्सटेंशन से मेल खाता है। उपरोक्त कोड काम नहीं करता है, क्या आप जानते हैं कि क्यों?


4
किस बारे में for i in $(ls *.java); do echo "do something with file $i"; done?
speakr

उस बयान को ठीक करने का कोई तरीका नहीं है?
एआरओओ

1
आप $iशाब्दिक स्ट्रिंग "* .java" से तुलना कर रहे हैं ; पैटर्न विस्तार यहां नहीं किया जाता है।
16

यदि आपके पास यह कथन ठीक करने के लिए, उपयोग करें if [[ $i == *.java ]]; then.. (डबल [[]] s और निर्विवाद * .java पर ध्यान दें)।
वह अन्य आदमी

2
पार्स न करेंls - @ chepner का जवाब स्वीकार करें
ग्लेन जैकमैन

जवाबों:


201

कोई फैंसी ट्रिक्स की जरूरत:

for i in *.java; do
    [ -f "$i" ] || break
    ...
done

गार्ड यह सुनिश्चित करता है कि यदि कोई मेल खाने वाली फाइलें नहीं हैं, तो लूप गैर-मौजूद फ़ाइल नाम को संसाधित करने के बिना बाहर निकल जाएगा *.java। में bash(या गोले कुछ इसी तरह का समर्थन), तो आप उपयोग कर सकते हैं nullglobविकल्प बस एक असफल मैच की अनदेखी करने और लूप के शरीर में प्रवेश नहीं।

shopt -s nullglob
for i in *.java; do
    ...
done

5
सबसे सरल तरीका एक और पैटर्न जोड़ना है for i in *.java *.cpp; do:। आप पैटर्न में सक्षम बढ़ाया है bashके साथ shopt -s extglob, आप लिख सकते हैं for i in *.@(java|cpp); do
चेप्टर

8
यह होगा अगर यह वास्तव में किसी भी फाइल से मेल खाता है। आपको इसका उपयोग करने की आवश्यकता है shopt -s nullglobताकि गैर-मिलान वाला पैटर्न शाब्दिक रूप से व्यवहार किए जाने के बजाय खाली अनुक्रम में फैल जाए।
23

1
@zygimantus हाँ, इसे तब तक करना चाहिए जब तक कि वर्तमान निर्देशिका वह स्क्रिप्ट कहाँ से चल रही है। यदि आप उस निर्देशिका में नहीं हैं, जो आप बनना चाहते हैं, तो cdआपको forलूप शुरू करने से पहले उस निर्देशिका में जाना चाहिए
danielsdesk

1
@ पुक यह आपके शेल विकल्पों पर निर्भर करता है। डिफ़ॉल्ट रूप से, गैर-मिलान पैटर्न को शाब्दिक स्ट्रिंग के रूप में माना जाता है। आप nullglobइसे एक खाली अनुक्रम के रूप में मान सकते हैं, या failglobइसे एक त्रुटि के रूप में मान सकते हैं। (यदि आप दोनों को सेट करते हैं, तो failglobपूर्वता लेता है।)
chepner

3
@chepner यह गैर विशेषज्ञों के लिए उपयोगी हो सकता है कि इसका उत्तर में संकेत दिया जाए क्योंकि कोई व्यक्ति इसे कॉपी पेस्ट कर सकता है और यह काम नहीं कर सकता है। एक आदर्श उदाहरण कोई है जो सभी "परिवर्तित किया जाएगा " के लिए .jpg "फ़ाइलें एक महत्वपूर्ण समारोह से बाहर ले जाने से पहले .png"
PUK

13

सही उत्तर है @ चेपर

EXT=java
for i in *.${EXT}; do
    ...
done

हालाँकि, यहां यह जांचने की एक छोटी सी चाल है कि फ़ाइल नाम में कोई एक्सटेंशन है या नहीं:

EXT=java
for i in *; do
    if [ "${i}" != "${i%.${EXT}}" ];then
        echo "I do something with the file $i"
    fi
done

extइसके बजाय एक चर के साथ यह कैसे होगा .java?
एआर '

13

सबफ़ोल्डर्स को पुन: जोड़ें,

for i in `find . -name "*.java" -type f`; do
    echo "$i"
done

इसके बजाय find . -name "*.java" -type f -exec echo \{\} \; आउटपुट के गलत इस्तेमाल से बचने के लिएfind
umläute

1
और अगर तुम नहीं, कम से कम तुम "$i"पाश के अंदर बोली चाहिए ।
ट्रिपल जू

2
यह काम नहीं करेगा अगर किसी भी फाइल में उनके नाम पर व्हाट्सएप हो।
कोडवर्ड

1
@codeforester मेरे पास यह मुद्दा था और मैंने इसे इस उत्तर से विधि का उपयोग करके ठीक किया है: askubuntu.com/a/343753/551184
fsinisi90

7

: लूप के साथ समाप्त सभी फ़ाइलों के माध्यम से .img, .bin, .txtप्रत्यय, और फ़ाइल नाम मुद्रित:

for i in *.img *.bin *.txt;
do
  echo "$i"
done

या एक पुनरावर्ती तरीके से (सभी उपनिर्देशिकाओं में भी खोजें):

for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
do
  echo "$i"
done

3

मैं फ़ाइलों के माध्यम से लूप के सही तरीके के बारे में अन्य उत्तरों से सहमत हूं। हालांकि ओपी ने पूछा:

उपरोक्त कोड काम नहीं करता है, क्या आप जानते हैं कि क्यों?

हाँ!

एक उत्कृष्ट लेख , परीक्षण के बीच अंतर क्या है, [और [?] विस्तार से बताता है कि अन्य अंतरों के बीच, आप कमांड के भीतर expression matchingया (जो शॉर्टहैंड के लिए ) का उपयोग नहीं कर सकते हैंpattern matchingtest[

नई परीक्षा [[पुराना परीक्षण] उदाहरण पेश करें

पैटर्न मिलान = (या ==) (उपलब्ध नहीं) [[$ नाम = एक]] || गूंज "नाम एक 'ए': $ नाम" से शुरू नहीं होता है

नियमित अभिव्यक्ति = ~ (उपलब्ध नहीं) [[$ (दिनांक) = ~ ^ शुक्र \ ... \ १३]] && गूंज "यह शुक्रवार १३ तारीख है!"
मेल मिलाना

तो यही कारण है कि आपकी स्क्रिप्ट विफल हो जाती है। यदि ओपी [[वाक्य-विन्यास के साथ उत्तर में रुचि रखता है (जिसमें [कमांड के रूप में कई प्लेटफार्मों पर समर्थित नहीं होने का नुकसान है ), तो मुझे इसे शामिल करने के लिए अपने उत्तर को संपादित करने में खुशी होगी।

संपादित करें: तालिका के रूप में उत्तर में डेटा को प्रारूपित करने का कोई भी तरीका उपयोगी होगा!


2

जैसा कि @chepner ने अपनी टिप्पणी में कहा है कि आप $ i की तुलना एक निश्चित स्ट्रिंग से कर रहे हैं।

उस स्थिति का विस्तार और सुधार करने के लिए जिसका उपयोग आपको [[]] regex ऑपरेटर = ~ के साथ करना चाहिए

उदाहरण के लिए:

for i in $(ls);do
    if [[ $i =~ .*\.java$ ]];then
        echo "I want to do something with the file $i"
    fi
done

= ~ के दाईं ओर के रेगेक्स का परीक्षण बाएं हाथ के ऑपरेटर के मूल्य के खिलाफ किया जाता है और इसे उद्धृत नहीं किया जाना चाहिए, (उद्धृत त्रुटि नहीं होगी लेकिन एक निश्चित स्ट्रिंग के खिलाफ तुलना करेगा और इसलिए सबसे अधिक संभावना विफल होगी "

लेकिन ग्लोब का उपयोग करने पर @chepner का उत्तर बहुत अधिक कुशल तंत्र है।


यह एक चर के साथ कैसे होगा extइसके बजाय.java ?
AR89

1
ack, एक नियमित अभिव्यक्ति के लिए कोई ज़रूरत नहीं है: if [[ $i == *.java ]]या if [[ $i == *.$ext ]]। लेकिन पार्स ls नहीं है
ग्लेन जैकमैन

1

मुझे यह उपाय काफी उपयोगी लगा। इसमें -orविकल्प का उपयोग किया गया है find:

find . -name \*.tex -or -name "*.png" -or -name "*.pdf"

यह विस्तार के साथ फ़ाइलें मिलेगा tex, pngऔर pdf

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