यदि यह सफल है तो कमांड के आउटपुट को पाइप करें


14
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`

मैं दूसरी कमांड को निष्पादित करना चाहता था ( head -1) केवल तभी जब पहली कमांड सफल हो। मैं इस आदेश को कैसे सुधारूं?


आपको सफल से क्या मतलब है? lsअसफल नहीं होगा।
मट्टियो

2
लेकिन अगर मेल नहीं हैं तो ग्लोब विफल हो सकता है।
ट्रिपल

जवाबों:


8

इसे इस्तेमाल करे:

INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`

ध्वज को पास xargsकरने से -rयह केवल तभी चल सकेगा basenameजब मानक इनपुट ( head -1) से कम से कम एक आइटम को पढ़ता है ।

head -1 चलेगा, लेकिन आप इससे कोई आउटपुट नहीं देखेंगे या कैप्चर नहीं करेंगे।

इसके अलावा, यदि आप उपयोगकर्ता से कोई त्रुटि आउटपुट नहीं देखना चाहते हैं, तो आप 's stderr' स्ट्रीम को lsपुनर्निर्देशित कर सकते हैं ।ls/dev/null

INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`

यह भी ध्यान दें कि मैंने उद्धरण चिह्नों को चारों ओर जोड़ा $MY_DIR। इस तरह, यदि $MY_DIRरिक्त स्थान होते हैं, तो कमांड विफल नहीं होगी ।

यदि आप आधुनिक आवरण जैसे बैश का उपयोग कर रहे हैं, तो आपको $( )बैकटिक्स के बजाय कैप्चर शेल का उपयोग करना चाहिए । आपको अपने चर की शैली को बदलने पर भी विचार करना चाहिए। आपको आम तौर पर लिपियों में सभी-अपरकेस चर नामों का उपयोग करने से बचना चाहिए। वह शैली आम तौर पर आरक्षित और पर्यावरण चर के लिए आरक्षित है।

input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)

अगर कोई फ़ाइल नहीं है, तो क्या यह b0rk नहीं है?
मेल बॉयस

असल में: ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basenameकाम करता है।
मेल बॉयस

@MelBoyce: मैंने इसे अपने उत्तर में जोड़ दिया है। धन्यवाद।

एलएस अंतःक्रियात्मक रूप से फ़ाइल जानकारी को देखने के लिए एक उपकरण है। इसका उत्पादन मनुष्यों के लिए स्वरूपित है और स्क्रिप्ट में कीड़े पैदा करेगा। इसके बजाय ग्लब्स का उपयोग करें या खोजें। समझें क्यों: mywiki.wooledge.org/ParsingLs
Cinelli

@ कैंसर: यह सच है। मैं सिर्फ सवाल का जवाब दे रहा था।

9

एक पाइप लाइन में, सभी कमांड शुरू होते हैं और समवर्ती रूप से चलते हैं, एक के बाद एक नहीं। तो आपको आउटपुट को कहीं स्टोर करने की आवश्यकता है।

if ls_output=$(ls -rtd -- "$MY_DIR"/FILE.*.xml); then
  first_file=$(printf '%s\n' "$ls_output" | head -n 1)
  first_file_name=$(basename -- "$first_file")
fi

ध्यान दें कि यह मानती है कि फ़ाइल नाम में न्यूलाइन वर्ण नहीं हैं। उपयोग करने xargsसे रिक्त पात्रों, एकल और दोहरे उद्धरण और बैकस्लैश के साथ समस्याओं का भी अर्थ होगा। निर्गत चर को छोड़ने से अंतरिक्ष, टैब और वाइल्डकार्ड वर्णों की समस्या होगी। भूलने --का मतलब होगा कि फ़ाइल नाम के साथ समस्याएँ शुरू होती हैं -

zshवर्णों पर उन प्रतिबंधों के बिना सबसे पुरानी फ़ाइल का बेसनेम प्राप्त करने के लिए (एक कमांड के तर्कों के सीमित आकार की समस्या से भी बचा जाता है):

 first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))

यदि कोई मेल नहीं है, तो वह आदेश विफल हो जाएगा और स्क्रिप्ट को निरस्त कर देगा। आप भी कर सकते हैं:

 first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))

जिस स्थिति में first_file_nameसरणी में 1 तत्व होगा यदि मैच या 0 है तो नहीं। आप तब कर सकते हैं:

 if (($#first_file_name)); then
    printf 'Match: %s\n' $first_file_name
 else
    echo >&2 No match
 fi

4

निर्देशिका में नवीनतम संशोधित फ़ाइल खोजें:

latest() {
  local file path=${1:-.} ext=${2-} latest
  for file in "${path%/}"/*"$ext"; do 
    [[ $file -nt $latest ]] && latest=$file
  done
  [[ $latest ]] && printf '%s\n' "$latest"
}

उपयोग: latest [directory/path/ [.extension]]

कॉल आउट करने के बजाय basename, पैरामीटर विस्तार का उपयोग करें।

in_file=$(latest in/my/dir .xml)
base_fn=${in_file##*/} base_fn=${base_fn%.*}

इन सामग्रियों वाली निर्देशिका में:

foo.xml bar.xml baz.xml newest.xml

Base_fn वैरिएबल की सामग्री इस प्रकार होगी: newest

अपने अनुरोध के उद्देश्य की पूर्ति के लिए इसका उचित उपयोग करें:

check_dir=/path/to/check
check_ext=.xml
if in_file=$(latest "$check_dir" "$check_ext"); then
  base_fn=${in_file##*/} base_fn=${base_fn%.*}
else
  printf '%s\n' "No file found in $check_dir" >&2
fi

संपादित करें: प्रश्न की समीक्षा करने पर, मैंने महसूस किया है कि lsविचाराधीन कमांड एक निर्देशिका में सबसे पुरानी फ़ाइल की तलाश में है। इसी फ़ंक्शन को फिर से नाम दिया जा सकता है oldestऔर इसके [[ $file -ot $oldest ]] && oldest=$fileबजाय समान प्रभाव प्राप्त कर सकते हैं। किसी भी भ्रम के लिए माफी।

ध्यान देने वाली महत्वपूर्ण बात यह है कि आप पूरी तरह से मानव जाति में कभी भी किसी भी परिस्थिति में, ls के आउटपुट को पार्स नहीं करना चाहिए। कभी नहीँ।


ध्यान दें कि ls-based दृष्टिकोण के विपरीत , यदि सीमलिंक हैं, तो सीमलिंक के लक्ष्य के संशोधन समय पर विचार किया जाएगा ( उसी व्यवहार को प्राप्त -Lकरने के lsलिए विकल्प जोड़ें )।
स्टीफन चेज़लस

0

मुझे लगता है कि यहाँ सबसे अच्छा विकल्प है:

ls -rf $MY_DIR/FILE.*.xml
if [ $? -eq 0 ]; then
      INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml|head -1|xargs basename `
else
      echo "Error!"
fi

अगर कोई फाइल नहीं है, तो ls का रिटर्न कोड 2 है, लेकिन अगर यह पाया जाता है कि कुछ फाइल 0 होगी।


2
के $?खिलाफ तुलना करने के बजाय 0, आप ऐसा कर सकते हैं if ls -rf $MY_DIR/FILE.*.xml ; then:।

इसके अलावा, आप पहले कॉमैंड के आउटपुट को रीडायरेक्ट कर सकते हैं /dev/nullls -rf $MY_DIR/FILE.*.xml &> /dev/null। इस तरह, उपयोगकर्ता अतिरिक्त आउटपुट नहीं देखेगा।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.