मैं शेल चर में कमांड के आउटपुट को कैसे निर्दिष्ट कर सकता हूं?


76

मैं एक चर के लिए एक अभिव्यक्ति का परिणाम असाइन करना चाहता हूं और इसे एक स्ट्रिंग के साथ समेटना चाहता हूं, फिर इसे गूंज। यहाँ मुझे क्या मिला है:

#!/bin/bash
cd ~/Desktop;
thefile= ls -t -U | grep -m 1 "Screen Shot";
echo "Most recent screenshot is: "$thefile;

लेकिन यह आउटपुट:

Screen Shot 2011-07-03 at 1.55.43 PM.png
Most recent screenshot is: 

इसलिए, ऐसा लगता है कि इसे असाइन नहीं किया $thefileजा रहा है, और इसे निष्पादित होते ही प्रिंट किया जा रहा है।


जवाबों:


108

एक शेल असाइनमेंट एक एकल शब्द है, जिसमें समान चिह्न के बाद कोई स्थान नहीं है। तो आपने जो लिखा है वह एक खाली मान प्रदान करता है thefile; इसके अलावा, चूंकि असाइनमेंट को एक कमांड के साथ समूहीकृत किया गया है, यह thefileएक पर्यावरण चर बनाता है और असाइनमेंट उस विशेष कमांड के लिए स्थानीय है, अर्थात केवल lsअसाइन किए गए मान को देखने के लिए कॉल ।

आप कमांड के आउटपुट को कैप्चर करना चाहते हैं, इसलिए आपको कमांड प्रतिस्थापन का उपयोग करने की आवश्यकता है :

thefile=$(ls -t -U | grep -m 1 "Screen Shot")

(कुछ साहित्य एक वैकल्पिक वाक्यविन्यास दिखाता है thefile=`ls …`; बैकक्वाइन सिंटैक्स डॉलर-कोष्ठक सिंटैक्स के बराबर है सिवाय इसके कि बैकक्वाट्स के अंदर उद्धृत करना कभी-कभी अजीब होता है, इसलिए बस उपयोग करें $(…)।)

आपकी स्क्रिप्ट के बारे में अन्य टिप्पणी:

  • संयोजन -t(समय के अनुसार) के साथ -U(सॉर्ट नहीं) कोई मतलब नहीं है; बस उपयोग करें -t
  • grepस्क्रीनशॉट का उपयोग करने के बजाय , पहली फ़ाइल कैप्चर करने के लिए वाइल्डकार्ड पास करना lsऔर उसका उपयोग करना अधिक स्पष्ट है head:

    thefile=$(ls -t *"Screen Shot"* | head -n 1)
  • यह आम तौर पर के उत्पादन को पार्स करने के लिएls एक बुरा विचार है । यह काफी बुरी तरह से विफल हो सकता है अगर आपके पास गैर-अक्षर वाले वर्णों के नाम हैं। हालाँकि, दिनांक के अनुसार फ़ाइलों को सॉर्ट करना मुश्किल है ls, इसलिए यह एक स्वीकार्य समाधान है यदि आपको पता है कि आपके पास फ़ाइल नामों में अनपेक्षित वर्ण या बैकस्लैश नहीं होंगे।

  • हमेशा चर प्रतिस्थापन के आसपास दोहरे उद्धरण चिह्नों का उपयोग करें , अर्थात यहां लिखें

    echo "Most recent screenshot is: $thefile"

    दोहरे उद्धरण चिह्नों के बिना, वैरिएबल का मान पुन: उपयोग किया जाता है, जो व्हाट्सएप या अन्य विशेष वर्णों को शामिल करने पर परेशानी पैदा करेगा।

  • आपको किसी पंक्ति के अंत में अर्धविराम की आवश्यकता नहीं है। वे बेमानी हैं, लेकिन हानिरहित हैं।
  • एक शेल स्क्रिप्ट में, यह अक्सर शामिल करने के लिए एक अच्छा विचार है set -e। यह शेल से बाहर निकलने के लिए कहता है यदि कोई कमांड विफल हो जाता है (नॉनज़रो स्थिति वापस करके)।

यदि आपके पास GNU है (विशेष रूप से यदि आप गैर-एम्बेडेड Linux या Cygwin चला रहे हैं), तो सबसे हाल की फ़ाइल को खोजने के लिए एक और तरीका है: findफ़ाइलों और उनकी तिथियों की सूची, और उपयोग करें sortऔर tailसबसे छोटी फ़ाइल निकालने के लिए।

thefile=$(find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%T@ %p" |
          sort -k 1n | tail -n 1)

यदि आप इस स्क्रिप्ट को बैश के बजाय zsh में लिखने के लिए तैयार हैं, तो नवीनतम फ़ाइल को पकड़ने का एक बहुत ही आसान तरीका है, क्योंकि zsh में ग्लोब क्वालिफायर हैं जो वाइल्डकार्ड को न केवल नामों पर, बल्कि फ़ाइल मेटाडाटा पर भी मेल खाते हैं। (om[1])पैटर्न के बाद का हिस्सा ग्लोब क्वालिफायर है; omबढ़ती उम्र से मेल खाता है (यानी संशोधन के समय, सबसे पहले नया) और [1]केवल पहला मैच निकालता है। पूरे मैच को कोष्ठकों में होना चाहिए क्योंकि यह तकनीकी रूप से एक सरणी है, क्योंकि ग्लोबिंग फाइलों की एक सूची देता है, भले ही [1]इसका मतलब यह हो कि इस विशेष मामले में सूची में (सबसे अधिक) एक फ़ाइल शामिल है।

#!/bin/zsh
set -e
cd ~/Desktop
thefile=(*"Screen Shot"*(om[1]))
echo "Most recent screenshot is: $thefile"

7
वाह! अधिक जानकारी से मैं संभवतः उम्मीद कर सकता था। आपके उत्तर के लिए कई बार धन्यवाद; मैं वास्तव में आपके द्वारा डाले गए सभी प्रयासों की सराहना करता हूं! आपने मुझे सिर्फ यह दिखाया है कि मैं वास्तव में बहुत कुछ सीखना चाहता हूं। मैं बैश पर एक किताब खरीदने के लिए तैयार हूं: पी।
नाथन जी।

3
यही मैं निश्चित उत्तर कहूंगा ! :)
एलेक्स

4

यदि आप इसे मल्टीलाइन / मल्टीपल कमांड / एस के साथ करना चाहते हैं तो आप ऐसा कर सकते हैं:

output=$( bash <<EOF
#multiline/multiple command/s
EOF
)

या:

output=$(
#multiline/multiple command/s
)

उदाहरण:

#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"

आउटपुट:

first
second
third

यह एक अच्छा जवाब है। क्या कोई तरीका है कि मैं एक चर को कमांड के हिस्से के रूप में निर्दिष्ट कर सकता हूं? उदाहरण के लिएoutput=$(echo $someVariable)
जैच स्मिथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.