अगर किसी फ़ाइल को बैश में मौजूद है तो परीक्षण करने के लिए लूप


94

मैं एक शेल स्क्रिप्ट पर काम कर रहा हूं, जो केवल txt फ़ाइल पर कुछ परिवर्तन करता है यदि यह मौजूद है, हालांकि यह परीक्षण लूप काम नहीं करता है, मुझे आश्चर्य है कि क्यों? धन्यवाद!

while [ ! -f /tmp/list.txt ] ;
do
      sleep 2
done

3
मैं यह नहीं कह सकता कि मैं हैरान हूँ; वह पाश कुछ भी बदलने का प्रयास नहीं करता है।
इग्नासियो वाज़क्वेज़-अब्राम्स

अर्ध-बृहदान्त्र बेमानी है। किस तरह से वह परीक्षण लूप काम नहीं करता है? जब तक फ़ाइल /tmp/list.txt मौजूद है, तब तक यह 2 सेकंड के लिए सो जाएगा।
जोनाथन लेफ़लर

5
मेरे लिए काम करता है - जब स्क्रिप्ट के बाहर फ़ाइल बनाई जाती है तो लूप समाप्त हो जाता है।

1
वास्तव में, यह लूप केवल तब तक प्रतीक्षा करने के लिए कार्य करता है जब तक कि फ़ाइल नहीं होती है, मेरी स्क्रिप्ट के बाकी परिवर्तन करते हैं ...: पी
ज़ेनेट

1
तब जबकि पाश काम करता है, यह सिर्फ मुझे है ... क्षमा करें।
ज़ीनत

जवाबों:


145

जब आप कहते हैं कि "काम नहीं करता है", तो आप कैसे जानते हैं कि यह काम नहीं करता है?

यदि फ़ाइल वास्तव में जोड़कर मौजूद है, तो आप यह पता लगाने की कोशिश कर सकते हैं:

while [ ! -f /tmp/list.txt ]
do
  sleep 2 # or less like 0.2
done
ls -l /tmp/list.txt

आप यह भी सुनिश्चित कर सकते हैं कि आप 'इको $ शेल' लिखकर बैश (या संबंधित) शेल का उपयोग कर रहे हैं। मुझे लगता है कि CSH और TCSH इस लूप के लिए थोड़ा अलग अर्थ का उपयोग करते हैं।


आप उल्टे फ़ाइल चेक का उपयोग क्यों कर रहे हैं? इसके बजाय [-f /tmp/list.txt] का उपयोग नहीं किया जाना चाहिए?
वलंट

2
@valentt नहीं हेव लूप का शाब्दिक अर्थ है "जबकि फ़ाइल मौजूद नहीं है नींद नहीं है" .. यदि आप '
नॉट

2
1 पंक्ति में:while [ ! -f /tmp/list.txt ]; do sleep 2; done; ls -l /tmp/list.txt
ढोल

55

यदि आप linux पर हैं और इनोटिफ़ाइ-टूल्स स्थापित हैं, तो आप यह कर सकते हैं:

file=/tmp/list.txt
while [ ! -f "$file" ]
do
    inotifywait -qqt 2 -e create -e moved_to "$(dirname $file)"
done

यह हर "एक्स" सेकंड को मतदान करते समय नींद से शुरू की गई देरी को कम करता है। आप अधिक घटनाओं को जोड़ सकते हैं यदि आप अनुमान लगाते हैं कि उनकी आवश्यकता है।


4
दक्षता के लिए +1। नींद के साथ पूल बदसूरत है। Inotifywait नहीं जानने वाले लोगों के लिए - यह पैकेज inotify-tools में है।
माइकल Micrajer

7
यह एक बहुत आसान उपकरण है। किसी के लिए भी यह क्यों सोचता है कि लूप, यह निर्माण और प्रतीक्षा के बीच संभावित दौड़ की स्थितियों से निपटने के लिए है और क्योंकि इनोटिफ़ाइवाइट को --excludeफ़ाइल नाम को फ़िल्टर करना है, लेकिन फ़ाइल नाम के अलावा--include सब कुछ अनदेखा नहीं करना है । उपर्युक्त आदेश को यद्यपि के बजाय तर्क का उपयोग करना चाहिए । -qq>&/dev/null
क्रेग रिंगर

t है --timeout, चेकिंग की फ्रीक्वेंसी, नहीं? Inotifywait की बात यह है कि कोई मतदान नहीं है
एलेक्स डीन

1
@AlexDean दौड़ की स्थिति को रोकने के लिए समय समाप्त होता है। नींद के साथ मतदान धीमा है क्योंकि नींद के दौरान लूप बाहर नहीं निकलेगा, लेकिन अगर कोई ईवेंट देखता है तो टाइमआउट से पहले इनोटिफ़ाइवाइट बाहर निकल जाएगा।
yingted

1
@AlexDean हाँ, लेकिन यह एक TOCTTOU दौड़ की स्थिति को रोकने के लिए आवश्यक है। अन्यथा, inotifywaitअनिश्चित काल तक लटका रह सकता है यदि कोई फ़ाइल घटनाओं को सुनने से ठीक पहले बनाई जाती है।
शाम

4

मैं एक ही समस्या थी, डाल! कोष्ठक के बाहर;

while ! [ -f /tmp/list.txt ];
do
    echo "#"
    sleep 1
done

इसके अलावा, यदि आप लूप के अंदर एक इको जोड़ते हैं तो यह आपको बताएगा कि आप लूप में आ रहे हैं या नहीं।


2

मैं एक समान मुद्दे में भाग गया और इसने मुझे यहां तक ​​पहुंचाया, इसलिए मैं किसी ऐसे व्यक्ति के लिए अपना समाधान छोड़ना चाहता था जो समान अनुभव करता हो।

मैंने पाया कि अगर मैं भागा cat /tmp/list.txtतो फ़ाइल खाली होगी, भले ही मैं निश्चित था कि वहाँ सामग्री तुरंत फ़ाइल में रखी जा रही थी। अगर यह उम्मीद के sleep 1;मुताबिक cat /tmp/list.txtकाम करता है, तो मैं इससे पहले ही बाहर हो जाता हूं । फ़ाइल के निर्माण के समय और उसके लिखे जाने के समय, या उन रेखाओं के साथ कुछ होने में देरी हुई होगी।

मेरा अंतिम कोड:

while [ ! -f /tmp/list.txt ];
do
    sleep 1;
done;
sleep 1;
cat /tmp/list.txt;

आशा है कि यह किसी को निराश करने वाले आधे घंटे को बचाने में मदद करता है!


1

@ ज़ैन-हूपर की तरह, मुझे एनएफएस पर समान समस्या थी। समानांतर / वितरित फाइलसिस्टम पर आपके बीच एक मशीन पर एक फाइल बनाने और दूसरी मशीन को "देखने" के लिए अंतराल "यह बहुत बड़ा हो सकता है, इसलिए मैं लूप के बाहर निकलने से पहले फ़ाइल के निर्माण के बाद एक पूर्ण मिनट तक इंतजार कर सकता हूं (और वहाँ भी एक "पहले से ही नष्ट कर दिया फ़ाइल" देख "" के बाद है।

यह भ्रम पैदा करता है कि स्क्रिप्ट "काम नहीं करती है" , जबकि वास्तव में यह फाइलसिस्टम है जो गेंद को गिरा रहा है।

मुझे यह पता लगाने में थोड़ा समय लगा, आशा है कि यह किसी को कुछ समय बचाता है।

PS यह भी "बासी फ़ाइल हैंडलर" त्रुटियों की एक कष्टप्रद संख्या का कारण बनता है।


0

बाश और श दोनों के साथ काम करता है:

touch /tmp/testfile
sleep 10 && rm /tmp/testfile &
until ! [ -f /tmp/testfile ]
do
   echo "testfile still exist..."
   sleep 1
done
echo "now testfile is deleted.."

0

यहां टाइमआउट के साथ एक संस्करण दिया गया है ताकि एक समय के बाद लूप एक त्रुटि के साथ समाप्त हो जाए:

# After 60 seconds the loop will exit
timeout=60

while [ ! -f /tmp/list.txt ];
do
  # When the timeout is equal to zero, show an error and leave the loop.
  if [ "$timeout" == 0 ]; then
    echo "ERROR: Timeout while waiting for the file /tmp/list.txt."
    exit 1
  fi

  sleep 1

  # Decrease the timeout of one
  ((timeout--))
done

-3

इसको ऐसे करो

while true
do
  [ -f /tmp/list.txt ] && break
  sleep 2
done
ls -l /tmp/list.txt
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.