bash: stderr को स्टोर करने के लिए एक वैरिएबल का उपयोग करें। स्टडआउट पुनर्निर्देशन


17

क्या स्क्रिप्ट में कमांड विकल्प जोड़ने जैसे चर के माध्यम से stdout और stderr को पुनर्निर्देशित करने का कोई तरीका है?

उदाहरण के लिए मेरे पास एक स्क्रिप्ट है:

#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
mkdir $OPT 123/123/123 $TEST

मैं देख सकता हूं कि ऑप्ट को -pबिना किसी समस्या के बदल दिया गया है और बैश इसे विकल्प के रूप में व्याख्या करता है। लेकिन डायरेक्टरी नाम के रूप में पुनर्निर्देशन व्याख्या करता है।

$ ./test.sh 
+ TEST='>/dev/null 2>&1'
+ OPT='-p -v'
+ mkdir -p -v 123/123/123 '>/dev/null' '2>&1'
mkdir: created directory `123/123'
mkdir: created directory `123/123/123'
mkdir: created directory `>/dev'
mkdir: created directory `>/dev/null'
mkdir: created directory `2>&1'

क्या बाश कहने का कोई तरीका है, कि $ VAR पुनर्निर्देशन है, डायर नाम नहीं।

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

जवाबों:


18

एक अन्य समाधान निम्नलिखित हो सकता है:

#!/bin/bash

verbose=0

exec 3>&1
exec 4>&2

if ((verbose)); then
  echo "verbose=1"
else
  echo "verbose=0"
  exec 1>/dev/null
  exec 2>/dev/null
fi

echo "this should be seen if verbose"
echo "this should always be seen" 1>&3 2>&4

फिर 1>&3 2>&4केवल उन कमांड्स को जोड़ें जिनमें से आप आउटपुट देखना चाहते हैं।


महान। यह वास्तव में वह चीज है जिसके लिए मैंने देखा था। धन्यवाद।
भीड़

मैंने लिखा है एक लेख को समझाने के लिए कि यह कैसे काम करता है
transang

5

"कैसे" को अन्य उत्तरों में अच्छी तरह से समझाया गया है; मैं "क्यों" को संबोधित करना चाहता हूं ओपी का कोड काम नहीं करता है।

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

दूसरे शब्दों में, एक बार चर का विस्तार करने के बाद इसे पुनर्निर्देशन चरित्र ( <या >, आदि) के लिए "बहुत देर हो चुकी" माना जाता है, क्योंकि शेल ने पहले ही पहचान लिया है कि कमांड स्ट्रिंग के किन हिस्सों को पुनर्निर्देशन के रूप में संभालने वाला है।

आगे पढ़ने के लिए, निम्न चरण 1 और 3 देखें:

LESS='+/^SIMPLE COMMAND EXPANSION' man bash

3

यह एक "निर्देशिका नाम" के रूप में व्याख्या नहीं कर >रहा है, उद्धृत किया जा रहा है, इसलिए इसका शाब्दिक रूप से इलाज किया जा रहा है (अधिक विशेष रूप से, आप स्ट्रिंग भेज रहे हैं >dev/null 2>&1। आपके आस-पास होने का एकमात्र तरीका evalएक नए शेल का उपयोग या स्पॉन करना है।

जैसा कि आपके "क्रिया" के लिए आपके प्रश्न में बताया गया है, बस इसके बजाय यह करें:

verbose=1
if (( verbose )); then
    mkdir -v -p /foo
else
    mkdir -p /foo > /dev/null 2>&1
fi

1

आपके चर में बहुत सारे स्थान हैं, जिनका सही तरीके से मूल्यांकन नहीं किया जाएगा। आप इसे evalसेट करने के लिए उपयोग करना चाहेंगे ।

#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
eval mkdir $OPT 123/123/123 $TEST

यह $ OPT को एक के बजाय दो तर्कों ( -pऔर -v) में विभाजित करने की अनुमति देगा ( और ) -p -v$ TEST के साथ। इसका उपयोग करने के लिए बदल दिया गया /dev/nullक्योंकि यह बहुत कम संभावना है कि आपके पास devवर्तमान निर्देशिका में एक निर्देशिका होगी ।


0

enzotib का उत्तर कुछ अच्छी फ़ाइल डिस्क्रिप्टर मैजिक का उपयोग करता है, लेकिन एक सरल उपाय यह होगा कि आप केवल evalलाइन का उपयोग करें (जो प्रक्रिया उपरि को जोड़ता है, हालाँकि):

$ rm /tmp/foo
$ ll /tmp/foo
ls: cannot access /tmp/foo: No such file or directory
$ FOO=">/tmp/foo"
$ date $FOO
date: invalid date '>/tmp/foo'
$ cat /tmp/foo
cat: /tmp/foo: No such file or directory
$ eval date $FOO
$ cat /tmp/foo
Thu Dec 13 14:08:17 EST 2018
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.