बैश में लूप एन बार कैसे दोहराएं


9

मेरे पास नीचे का परिदृश्य है जैसे:

if [file exists]; then
   exit   
elif
   recheck if file exist (max 10 times)
   if found exit else recheck again as per counter  
fi 

यह गोले में एक बहुत ही बुनियादी विशेषता है। क्या आपने भी इस पर शोध किया?
पेश्के

हाँ। लेकिन मेरे कोड से अपेक्षित आउटपुट नहीं मिल रहा है। जितना संभव हो उतना संक्षिप्त रूप में लिखना चाहते हैं
Rocky86

1
@Peskeke, ठीक है, उन्हें कम से कम क्या चाहिए, तीन बुनियादी सुविधाएँ (लूप, सशर्त, फ़ाइल का परीक्षण करना, एक लूप से बाहर निकलना)। कम से कम सवाल काफी स्पष्ट है क्योंकि यह है। हालांकि इसमें रॉकी की कोशिश का एक स्केच हो सकता है, लेकिन फिर कोई भी किसी भी तरह से जवाब में इसे फिर से लिख देगा। ;)
ilkachachu

जवाबों:


9

इस लूप को करने के कई तरीके हैं।

ksh93सिंटैक्स के साथ (द्वारा समर्थित zshऔर bash):

for (( i=0; i<10; ++i)); do
    [ -e filename ] && break
    sleep 10
done

किसी भी POSIX जैसे शेल के लिए:

n=0
while [ "$n" -lt 10 ] && [ ! -e filename ]; do
    n=$(( n + 1 ))
    sleep 10
done

फिर से फ़ाइल के अस्तित्व का परीक्षण करने से पहले दोनों लूप प्रत्येक पुनरावृत्ति में 10 सेकंड सोते हैं।

लूप समाप्त होने के बाद, आपको यह पता लगाने के लिए फ़ाइल के अस्तित्व के लिए अंतिम बार परीक्षण करना होगा कि क्या लूप 10 बार चलने के कारण बाहर निकल गया या फ़ाइल प्रदर्शित होने के कारण।

यदि आप चाहते हैं, और यदि आपके पास inotify-tools का उपयोग है, तो आप sleep 10कॉल को बदल सकते हैं

inotifywait -q -t 10 -e create ./ >/dev/null

यह वर्तमान निर्देशिका में एक फ़ाइल निर्माण घटना होने की प्रतीक्षा करेगा, लेकिन 10 सेकंड के बाद समय समाप्त हो जाएगा। इस तरह आपका लूप जैसे ही दिए गए फ़ाइल नाम के रूप में दिखाई देगा (यदि यह दिखाई दिया) तो बाहर निकल जाएगा।

पूर्ण कोड, inotifywait( sleep 10यदि आप ऐसा नहीं चाहते हैं तो बदलें ), जैसा दिख सकता है

for (( i=0; i<10; ++i)); do
    [ -e filename ] && break
    inotifywait -q -t 10 -e create ./ >/dev/null
done

if [ -e filename ]; then
    echo 'file appeared!'
else
    echo 'file did not turn up in time'
fi

Inotify के साथ, आप लगभग पूरे लूप को बदल सकते हैं। यदि फ़ाइल है तो बस परीक्षण करें, और यदि नहीं, तो 100 सेकंड के लिए inifyifywait। लगभग, फ़ाइल के बाद से निर्मित किया जा सकता सिर्फ परीक्षण और inotify के बीच, और आप पूर्ण 100 सेकंड के लिए सोने से पहले बाहर था समय ...
ilkkachu

1
@ilkachachu हाँ, यह एक अच्छा विचार है, लेकिन यहाँ मैं केवल inotifywaitड्रॉप-इन प्रतिस्थापन के रूप में उपयोग कर रहा हूँ sleep
Kusalananda

8

यदि गिनती एक चर नहीं है तो आप ब्रेस विस्तार का उपयोग कर सकते हैं:

for i in {1..10}   # you can also use {0..9}
do
  whatever
done

यदि गिनती एक चर है तो आप seqकमांड का उपयोग कर सकते हैं :

count=10
for i in $(seq $count)
do
  whatever
done

मैं केवल तभी लूप करना चाहता हूं जब फ़ाइल नहीं मिली (अधिकतम 10 बार)। अगर पाया गया कि तीसरी बार कहें तो सफलतापूर्वक बाहर निकलें
Rocky86

@ Rocky86: यह xenoid द्वारा प्रस्तावित समाधान का खंडन नहीं करता है। कोई भी आपको अंत तक गिनने के लिए मजबूर नहीं करता है ....
user1934428

मुझे यह पसंद है$(seq $count)
वर्कर

0
n=0
until [ "$((n+=1))" -gt 10 ]
do    <exists? command exit
done
echo oh noes!

हालांकि test -e file && exitअधिक लचीला है


प्रश्न चिह्न क्यों? ध्यान दें कि पुनर्निर्देश के लक्ष्य में ग्लब्स के लिए व्यवहार गोले के बीच भिन्न होता है।
स्टीफन चेजलस

2
ध्यान दें कि इसका फ़ाइल खोलने का साइड इफ़ेक्ट है, जो उदाहरण के लिए पोज़ोस के लिए काफी खराब हो सकता है (उदाहरण के लिए लिनक्स पर
सिम्लिंक

यहां तक ​​कि बैश में, जहां यह एक फ़ाइल की तरह दिखती है exists1जैसे कि, यह अभी भी त्रुटियों का एक गुच्छा प्रिंट करता है यदि / जब एक मिलान फ़ाइल नहीं मिली है। (इसके अलावा अगर इसमें कई मैच हैं, तो यह त्रुटि है।) मेरे द्वारा परीक्षण किया गया कोई अन्य शेल किसी भी मामले में त्रुटियां देता है ...
ilkkachu

@ikachachu - हाँ। यह थोथा बिंदु था। यदि त्रुटि होती है, तो स्क्रिप्ट रिपोर्ट करती है। यदि स्टेडर को दबाया जाना चाहिए, तो इसे दबाएं done 2<>/dev/null। क्या bashवह स्क्रिप्टेड है? मैंने सोचा कि यह केवल एक -iउदासीन संदर्भ में है। फिर भी, exists?एक भराव नाम जितना है file। लेकिन हाँ, मुझे रीडायरेक्ट में उद्धृत करने से नफरत है - अगर शिकंजा इतना ऊपर।
mikeserv

@ स्टीफन - कोई कारण नहीं, वास्तव में। लेकिन हाँ, फीफा, अपठ्य ... मैं क्यों उल्लेख किया test -e
mikeserv
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.