85

いくつかの実行時間の長いプロセスを呼び出す bash スクリプトがあります。処理上の理由から、これらの呼び出しの出力を変数にキャプチャしたいと考えています。ただし、これらは長時間実行されるプロセスであるため、rsync 呼び出しの出力を事後ではなくリアルタイムでコンソールに表示したいと考えています。

この目的のために、私はそれを行う方法を見つけましたが、テキストを /dev/stderr に出力することに依存しています。/dev/stderr への出力は良い方法ではないと感じています。

VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)

VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)

VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)

上記の例では、rsync を数回呼び出しており、処理中のファイル名を確認したいのですが、後で解析するため、最終的には出力を変数に入れたいと考えています。

これを達成するための「よりクリーンな」方法はありますか?

違いがある場合は、Ubuntu 12.04、bash 4.2.24 を使用しています。

4

5 に答える 5

90

シェルで &1 を複製し (私の例では 5 に)、サブシェルで &5 を使用します (親シェルの stdout (&1) に書き込むため):

exec 5>&1
FF=$(echo aaa|tee >(cat - >&5))
echo $FF

aaa を 2 回出力します。1 回目はサブシェルでのエコーが原因で、2 回目は変数の値を出力します。

あなたのコードで:

exec 5>&1
VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
# use the value of VAR1
于 2012-09-16T22:58:56.983 に答える
42

Op De Cirkelの答えには正しい考えがあります。さらに単純化することができます (の使用を避けますcat):

exec 5>&1
FF=$(echo aaa|tee /dev/fd/5)
echo $FF
于 2013-04-30T04:25:38.203 に答える
6

3 つ以上のファイル記述子を使用できます。ここで試してください:

http://tldp.org/LDP/abs/html/io-redirection.html

「開いている各ファイルには、ファイル記述子が割り当てられます。[2] stdin、stdout、および stderr のファイル記述子は、それぞれ 0、1、および 2 です。追加のファイルを開くために、記述子 3 から 9 が残っています。これらの追加のファイル記述子の 1 つを一時的な重複リンクとして stdin、stdout、または stderr に割り当てます。」

問題は、この結果を達成するためだけにスクリプトを複雑にする価値があるかどうかです。実際、あなたのやり方は間違っていません。

于 2012-09-16T22:41:35.117 に答える