Stdoutとstderrの両方を同じファイルにリダイレクトする場合は、command 1>file.txt 2>&1
またはcommand &>file.txt
を使用して行うことができます。しかし、command 1>file.txt 2>file.txt
の動作が上記の2つのコマンドと異なるのはなぜですか?
以下は検証コマンドです。
$ cat redirect.sh
#!/bin/bash
{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file.txt 2>&1
{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file1.txt 2>file1.txt
{ echo -e "error" 1>&2 && echo -e "output\noutput"; } 1>file2.txt 2>file2.txt
{ echo -e "output" && echo -e "error\nerror" 1>&2; } 1>file3.txt 2>file3.txt
{ echo -e "error\nerror" 1>&2 && echo -e "output"; } 1>file4.txt 2>file4.txt
$ ./redirect.sh
$ echo "---file.txt---"; cat file.txt;\
echo "---file1.txt---"; cat file1.txt; \
echo "---file2.txt---"; cat file2.txt; \
echo "---file3.txt---"; cat file3.txt; \
echo "---file4.txt----"; cat file4.txt;
---file.txt---
output
output
error
---file1.txt---
error
output
---file2.txt---
output
output
---file3.txt---
error
error
---file4.txt----
output
rror
結果を見る限り、command 1>file.txt 2>file.txt
を実行すると、2番目のエコー文字列が最初のエコー文字列を上書きするように見えますが、なぜそうなるのかはわかりません。 (どこかに参照がありますか?)
次の2つのことを知っておく必要があります。
このような変更は、read()
/readv()
、write()
/writev()
、lseek()
などを呼び出すプロセスによって実行されます。システムコール。 echo
コマンドは、もちろんwrite()
/writev()
を呼び出します。
だから何が起こるのですか:
command 1>file.txt 2>&1
は、シェルがファイルを1度だけ開くため、1つのファイルの説明のみを作成します。シェルは、標準出力と標準エラーファイル記述子をその単一のファイル記述にマップ両方します。標準出力に標準出力にduplicatesします。したがって、いずれかのファイル記述子を介した書き込みは、共有された現在のファイル位置を移動します。各書き込みは、前の共通ファイル記述の書き込みの後に行われます。ご覧のように、echo
コマンドの結果は互いに上書きしません。command 1>file.txt 2>file.txt
は、シェルが2つの明示的なリダイレクトに応答して同じファイルを2回開くため、twoファイルの説明を作成します。標準出力と標準エラーのファイル記述子は、2つの異なるファイルの説明にマップされ、次に同じ1つのファイルにマップされます。 2つのファイル記述には、完全に独立した現在のファイル位置があり、各書き込みは、同じファイル記述に対する直前の書き込みにすぐに行きます。結果を見るとわかるように、一方を介して書き込まれたものは、他方を介して書き込まれたものを、書き込みを実行する順序に応じてさまざまな方法で上書きできます。>
を使用すると、ファイルが上書きされます。 stdoutとstderrが2つの異なる操作でファイルに書き込んでいるため、最後に書き込んだ操作が最初の操作を上書きします。
できるよ:
command 1>>file.txt 2>>file.txt
または
command &>file.txt
bash v4以降のみ。
>>
は、以前の操作の出力を置き換えないようにファイルを追加するように指示します。
&>
は2>&1
を書くためのより簡単な方法です