web-dev-qa-db-ja.com

bashパイプ行の間でコマンドを実行します...?

多くのオーディオ処理を行う一連のパイプコマンドを実行したいと思います。擬似コードでは次のようになります。

command1 | command2 | command3

Command2とcommand3のうち、どちらも前のコマンドの出力を入力として受け取ります(通常のstdin/stdoutの動作)。

ここで、command1の直後に別のcommand1.1を実行したいと思います。これは、command1が完全に終了する前に実行してはならないことを除いて、command1とcommand2の間の実行パイプに接続されていません。

command1 [; after that run command1.1, even if command2 and command3 are still busy] command2 command3

しかし、bashでこれを行う方法がわかりません。 teeを試しましたが、パイプが作成されるとすぐにコマンドが実行されます。何か案は?

ありがとう!

4
cunei

これに関する重要な部分は「その後」です-UNIXパイプが「その後」について持っている唯一の概念は、通常は閉じるということですが、最初のコマンドが開始になった後、istの後ではなく実行されます終了

したがって、実行する必要があるのは、シェルスクリプトを使用することです。これは「次々に」という概念を持っています。

echo 'command1' > myscript.sh
echo 'command1.1 >&2' >> myscript.sh
chmod 755 myscript.sh

(もちろん、お気に入りのエディターを使用してそれを実現できます)、次に実行します

myscript.sh | command2 | command3

現在、command1の出力がシェルスクリプトの出力になるため、パイプが機能します。スクリプト内では、command1.1の出力はスクリプトのSTDERRにリダイレクトされるため、パイプではなく端末に送信されます。

4
Eugen Rieck

サブシェルにリダイレクトできます。

command1 & > >(command2 | command3) &
wait $!      # Wait end of process $! (actually the pid of command1)
command_1.1     

別の方法は、名前付きパイプを作成することです fifo
スクリプトは次のようになります

MYFIFO=/tmp/myfifo.$$
rm -f $MYFIFO
mkfifo $MYFIFO
command1 > $MYFIFO &
MYPROGRAM_PID=$!
cat $MYFIFO  | command2 | command3 &
wait $MYPROGRAM_PID   # Wait end of process $MYPROGRAM_PID
command_1.1     
4
Hastur

最も単純な構造は次のとおりです。

(command1 ; command1.1) | command2 | command3

これには2つの潜在的な問題があります。 command1.1がstdoutで出力を生成する場合、それはパイプを介して送信されます。さらに、command2は、command1.1が完了するまで、stdinにEOFを表示しません。

Stdoutとstderrのファイル記述子が両方とも同じファイル構造体を指しているコンテキストでパイプラインが最初に呼び出された場合、両方の問題を修正する簡単な方法があります。

(command1 ; exec 1>&2 command1.1) | command2 | command3

これにより、command1.1のstdoutは、パイプラインによってリダイレクトされなかったstderrを指すようになります。

最初にstdoutとstderrが2つの異なるファイル記述子である可能性がある場合、上記のアプローチは、最初のstdoutを別のファイル記述子番号に一時的に隠しておくことで使用できます。したがって、stdoutとstderrをcommand1.1から絶対に分離する必要がない限り、私はそのアプローチを採用しません。

完全を期すために、それを実行したい場合は、次のようになります。

(((exec 9>&- command1) ; exec 1>&9 9>&- command1.1) | exec 9>&- command2 | exec 9>&- command3) 9>&1
2
kasperd