いくつかの結果を生成するbashアプリケーションがあり、stdout
ユーザーが選択したファイルに結果をエコーしたいと思います。他の対話型メッセージも画面に表示されるため、>
結果をファイルに表示しようとするときにユーザーに明示的にリダイレクトを使用するように要求することはオプション(*)ではありません。そのメッセージもファイルに表示されるためです。
これで解決策がありましたが、見苦しいです。
if [ -z $outfile ]
then
echo "$outbuf" # Write output buffer to the screen (stdout)
else
echo "$outbuf" > $outfile # Write output buffer to file
fi
私は、toおよび他のものと$outfile
同じ変数を持つことを試みましたが、実際にstdoutに書き込むのではなく、その名前のファイルにのみ書き込みます。よりエレガントなソリューションはありますか?stdout
&1
(*) こんな目的でだまされて使うこともできますが、stderr
それも醜いと思いますか?
ベストアンサー1
まず、あなたはecho
任意のデータ出力を防止。
Linuxベースのシステム以外のシステムでは、次のものを使用できます。
logfile=/dev/stdout
Linuxでは、これはいくつかのタイプのstdoutで動作しますが、stdoutがソケットの場合は失敗します。または、stdoutが通常のファイルの場合、stdoutが現在作成されているファイルの場所にあるのではなく、ファイルが切り捨てられます。
それ以外の場合、Bourneのようなシェルには方法はありませんホームフレーズリダイレクト(次が利用可能eval
)
eval 'printf "%s\n" "$buf" '${logfile:+'> "$logfile"'}
変える変える、専用使用可能ファイル記述子:
exec 3>&1
[ -z "$logfile" ] || exec 3> "$logfile"
printf '%s\n' "$buf" >&3
これの1つの(マイナーな)欠点は、ksh
fd 3を除いて、スクリプトで実行されるすべてのコマンドでリークされることです。を使用すると、代わりにアクションを実行zsh
できますが、それに対応するアクションはありません。sysopen -wu 3 -o cloexec -- "$logfile" || exit
exec 3> "$logfile"
bash
別の一般的なイディオムは、次の関数を使用することです。
log() {
if [ -n "$logfile" ]; then
printf '%s\n' "$@" >> "$logfile"
else
printf '%s\n' "$@"
fi
}
log "$buf"