変数を介してstdoutとstderrをリダイレクトする方法はありますか(スクリプトにコマンドオプションを追加するなど)?
たとえば、次のスクリプトがあります。
#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
mkdir $OPT 123/123/123 $TEST
-p
OPTが問題なく交換され、bashがそれをオプションとして解釈するのがわかります。ただし、リダイレクトはディレクトリ名として解釈されます。
$ ./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'
bashで$ VARがディレクトリ名ではなくリダイレクトであると言える方法はありますか?
PS。私は間違った方向に行っているかもしれませんが、スクリプトではオプションで冗長な出力や冗長ではない出力を持っていると思います。ただし、冗長ではないモードでもいくつかの出力が必要なため、スクリプト内の一部のコマンドでstdoutとstderr全体をリダイレクトすることはできません。
答え1
別の解決策は次のとおりです。
#!/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
出力を表示するコマンドのみを追加します。
答え2
「方法」は他の答えでよく説明されています。 OPコードが動作しない「理由」を扱いたいです。
トーンは出力リダイレクトが表示される今後可変拡張。 リダイレクトは実際に実装変数が拡張された後(出力を変数に保存されたファイル名にリダイレクトできます)、シェルは識別する変数拡張前の後続処理のためのリダイレクトです。
つまり、変数が拡張されると、シェルがコマンド文字列のどの部分をリダイレクトとして処理するかをすでに識別しているため、文字(<
またはなど)リダイレクトを検討するのは「遅すぎました」ということです。>
詳細については、下記の手順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
答え4
変数に正しく評価されないスペースがたくさんあります。eval
設定するにはこの情報が必要です。
#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
eval mkdir $OPT 123/123/123 $TEST
これにより、$ OPTを1つの()ではなく2つのパラメータ(-p
および)に分割し、$ TESTと同じにすることができます。また、現在のディレクトリにディレクトリがない可能性が高いため、使用するように変更されました。-v
-p -v
/dev/null
dev