अगर-फेल हो जाता है तो मुझे कैसे असफलता मिलेगी


24

जब मैं इस कमांड को शेल में चलाता हूं (गैर-खाली निर्देशिका में)

find . -exec invalid_command_here {} \;

मैंने इसे प्राप्त किया:

find: invalid_command_here: No such file or directory
find: invalid_command_here: No such file or directory
find: invalid_command_here: No such file or directory

(और प्रत्येक फ़ाइल के लिए)

मुझे जरूरत है find पहली त्रुटि के बाद विफल होना। क्या इसे काम करने का कोई तरीका है? मैं उपयोग नहीं कर सकता xargs, क्योंकि मेरे पास मेरे रास्ते में जगह है, लेकिन मुझे एक त्रुटि कोड को वापस करने के लिए स्क्रिप्ट को कॉल करने की आवश्यकता है।

जवाबों:


30

यह एक सीमा है find POSIX मानक निर्दिष्ट करता है कि वापसी की स्थिति find जब तक निर्देशिकाओं को ट्रेस करते समय कोई त्रुटि नहीं हुई है; निष्पादित आदेशों की वापसी स्थिति इसमें दर्ज नहीं होती है।

आप कमांड को फ़ाइल या डिस्क्रिप्टर पर अपनी स्थिति लिख सकते हैं:

find_status_file=$(mktemp findstatus)
: >"$find_status_file"
find … -exec sh -c 'trap "echo \$?" EXIT; invalid_command "$0"' {} \;
if [ -s "$find_status_file" ]; then
  echo 1>&2 "An error occurred"
fi
rm -f "$find_status_file"

एक अन्य विधि, जैसा आपने खोजा था , xargs का उपयोग करना है। xargs कमांड हमेशा सभी फाइलों को प्रोसेस करता है, लेकिन यदि कोई भी कमांड नॉनजेरो स्टेटस देता है, तो स्टेटस 1 को लौटा देता है।

find … -print0 | xargs -0 -n1 invalid_command

फिर भी एक और तरीका बचना है find और इसके बजाय शेल में पुनरावर्ती ग्लोबिंग का उपयोग करें: **/ उपनिर्देशिकाओं की किसी भी गहराई का मतलब है। इसके लिए संस्करण 4 या बैश के ऊपर की आवश्यकता होती है; macOS 3.x संस्करण पर अटका हुआ है, इसलिए आपको इसे पोर्ट संग्रह से इंस्टॉल करना होगा। उपयोग set -e पहले कमांड पर स्क्रिप्ट को रोकना एक गैर-स्थिति को वापस करना

shopt -s globstar
set -e
for x in **/*.xml; do invalid_command "$x"; done

खबरदार कि 4.2 के माध्यम से 4.0 में, यह काम करता है लेकिन निर्देशिकाओं के प्रतीकात्मक लिंक का पता लगाता है, जो आमतौर पर वांछनीय नहीं है।

यदि आप बैश के बजाय zsh का उपयोग करते हैं, तो पुनरावर्ती ग्लोबिंग बिना किसी गोच के बॉक्स से बाहर काम करता है। Zsh डिफ़ॉल्ट रूप से OSX / macOS पर उपलब्ध है। Zsh में, आप बस लिख सकते हैं

set -e
for x in **/*.xml; do invalid_command "$x"; done

18

मैं इसके बजाय इसका उपयोग कर सकता हूं:

find . -name *.xml -print0 | xargs -n 1 -0 invalid_command

1

xargs एक विकल्प है। हालांकि, यह वास्तव में तुच्छ के साथ ऐसा करना आसान है find साथ ही उपयोग करके + के बजाय \;:

-exec  utility_name  [argument ...]   {} +

वहाँ से POSIX प्रलेखन :

यदि प्राथमिक अभिव्यक्ति को एक प्लस चिह्न द्वारा छिद्रित किया जाता है, तो प्राथमिक हमेशा सही के रूप में मूल्यांकन करेगा, और जिन नामों के लिए प्राथमिक मूल्यांकन किया जाता है, उन्हें सेट में एकत्रित किया जाएगा। कुल उपयोगिता के प्रत्येक सेट के लिए एक बार यूटिलिटी यूटिलिटी_नाम लागू किया जाएगा। प्रत्येक आह्वान शुरू होने के बाद शुरू होगा जब सेट में अंतिम pathname एकत्र किया जाता है, और पूर्ण होने से पहले उपयोगिता समाप्त हो जाएगी और अगले सेट में पहले pathname से पहले (यदि कोई हो) इस प्राथमिक के लिए एकत्रित है, लेकिन यह अन्यथा अनिर्दिष्ट है अन्य प्राइमरी के मूल्यांकन के पहले, दौरान या बाद में होता है। यदि कोई आह्वान गैर-शून्य मान को निकास स्थिति के रूप में लौटाता है, तो खोज उपयोगिता गैर-शून्य निकास स्थिति लौटाएगी। केवल दो वर्ण "{}" वाले तर्क को एकत्रित पथनाम के सेट से बदल दिया जाएगा, प्रत्येक पथनाम के साथ एक अलग तर्क के रूप में उसी क्रम में पारित किए गए तर्क के लिए पारित किया जाएगा, जिसे यह एकत्र किया गया था। दो या दो से अधिक पाथनामों के किसी भी सेट का आकार इस तरह सीमित होगा कि उपयोगिता का निष्पादन प्रणाली की {ARG_MAX} सीमा को पार करने का कारण नहीं बनता है। यदि केवल दो वर्ण "{}" वाले एक से अधिक तर्क मौजूद हैं, तो व्यवहार अनिर्दिष्ट है।

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