
関数を呼び出す bash スクリプトがあります。関数は、とりわけ、その出力をシンクするパイプラインを実行します。これを単純化するために、以下に例を示します。
#!/bin/bash
func() {
ls "$@" | sort | rev > /tmp/output
}
func "$@"
次に、次のように実行します。 必要な処理が実行され、ペイロードがファイルに配信されます。 画面には出力されません。
$ ./myscript .
さて、 を標準出力に出力したいとしますsort
。どうすればよいでしょうか?
次のようにして実現できます:
ls "$@" | sort | tee /dev/tty | rev > /tmp/output
ただし、/dev/tty
これは機能しないため、使用するのは間違いです。
$ ./myscript > myfile
関数内のパイプライン内から bash スクリプトの標準出力を参照するより正確な方法はありますか?
(私はArch Linuxでbash 4.3.0を使用しています)
答え1
私が考えられる最も簡単な方法は次のとおりです。
ls "$@" | sort | tee >(rev > /tmp/output)
はtee
1 つのコピーを STDOUT に送信します。その後に がなくなったため|
、これが継承され、リダイレクトされていない場合は TTY に、リダイレクトされてmyfile
いる場合は
に送信されます。もう 1 つのコピーは、rev > /tmp/output
その STDIN に送信されます。bash では、>(...)
括弧内の内容を実行し、 を>(...)
その STDIN に接続されたパイプへのパスに置き換えます。
答え2
他の答えはこれについて明確ではないので、他の(別の)方法は
exec 3>&1
ls | sort | tee /dev/fd/3 | rev > /tmp/output
のexec 3>&1
重複ファイル記述子 1 (stdout) をファイル記述子 3 として複製します。次に、の出力tee /dev/fd/3
のコピーをsort
そのファイル記述子に書き込みます。これはどのシェルでも動作するはずですが、オペレーティング システムに依存する可能性があります。OS に依存しないが、 固有のバリアントはbash
次のとおりです。
exec 3>&1
ls | sort | tee >( cat >&3 ) | rev > /tmp/output
ではbash
、実行中のプロセスへのパイプへのファイルハンドルを提供します。>(command)
command
任意の(?)シェルで、command >&fd
command
stdout は指定されたファイル記述子にリダイレクトされます。このファイル記述子は事前に確立されている必要があります。
より複雑なバージョンは、どの*nix (Posix)システムでも動作するはずですが、
pipe_to_stdout=$(mktemp -u)
mkfifo "$pipe_to_stdout"
cat "$pipe_to_stdout" &
ls | sort | tee "$pipe_to_stdout" | rev > /tmp/output
rm "$pipe_to_stdout"
cat
これは 2 番目の例 ( FIFO から読み取り、stdout に書き込む)とほぼ同じですが、シェル レベルでの煙と鏡の使用が少なくなります。
これらの回答は柔軟性があり、コマンドを並べ替えるだけで出力をls
標準出力に書き込むことができることに注意してください。