ループ出力リダイレクトがファイル名に依存するのはなぜですか?

ループ出力リダイレクトがファイル名に依存するのはなぜですか?

2つのファイルがあります:a.csvb.csv

echo $'a_header\na1' > a.csv
echo $'b_header\nb1' > b.csv

では、各行の最初の行を削除してから接続したいと思います。

for file in `ls *.csv`; do cat $file | tail -n +2 | cat; done 

ただし、前のコマンドの出力をファイルにリダイレクトすると、出力ファイル名によって異なる結果が表示されます。

for file in `ls *.csv`; do cat $file | tail -n +2 | cat; done > result
for file in `ls *.csv`; do cat $file | tail -n +2 | cat; done > result.csv

cat result
a1
b1

cat result.csv
a1
b1
b1

答え1

次のコマンドがある場合:

command > file

コマンドの標準出力(fd 1)はcommandファイルにリダイレクトされますfile。ファイルが存在しない場合、ファイルが生成されます。コマンドは通常、コマンド出力をファイル記述子1(stdout)にリダイレクトします。

上記の式(出力がファイルにリダイレクトされる場合)を使用する場合は、出力ストリームが開始される前にファイルが存在する必要があります。したがって、bashファイルを作成し(空)、stdoutに接続してcommandからファイル記述子への書き込みを開始します。

これはシェルによって処理されます。このコマンドは、匿名パイプに書き込むかファイルに書き込むかを知りません。


次のコマンドを実行します。

for file in `ls *.csv`; do cat $file | tail -n +2 | cat; done > result.csv

ここで何が起こるのかは、ファイルが空であるresult.csvということです。次に、(include)forで終わる各ファイルを繰り返します。その後、少なくともファイルが処理されます。 thenの2行目。これが結果ファイルに2行がある理由です。csvresult.csva.csvb.csvresult.csvresult.csvb1

関連情報