他の人が指摘しているように、read-echoループの代わりにcatまたはawkを使用することは、これを行うためのはるかに優れた方法です-空白のトリミングの問題(およびあなたが遭遇していない他のいくつか)を回避し、より速く実行します、少なくとも猫の場合は、単純にクリーンなコードです。それでも、read-echoループを正しく機能させるために努力したいと思います。
まず、空白のトリミングの問題です。readコマンドは、先頭と末尾の空白を自動的にトリミングします。これは、IFS変数を空白に設定して空白の定義を変更することで修正できます。また、readは、行末の円記号が次の行が継続であることを意味し、これと一緒に接続する必要があることを前提としています。これを修正するには、-r(raw)フラグを使用します。ここでの3番目の問題は、echoの多くの実装が文字列内のエスケープシーケンスを解釈することです(たとえば、\ nが実際の改行に変わる可能性があります)。これを修正するには、代わりにprintfを使用してください。最後に、一般的なスクリプトの衛生規則と同様に、実際に必要がない場合はcatを使用しないでください。代わりに入力リダイレクトを使用してください。これらの変更により、内部ループは次のようになります。
while IFS='' read -r line; do
printf "%s\n" "$line">>$OUTPUT
done <$f
...周囲のスクリプトには他にもいくつかの問題があります。使用可能な.textileファイルのリストとしてFILESを定義しようとする行には引用符が付いています。つまり、実際のファイルのリストに展開されることはありません。これを行う最良の方法は、配列を使用することです。
FILES=(../best-practices/*.textile)
...
for f in "${FILES[@]}"
(ファイル名のいずれかにスペースやその他の面白い文字が含まれている場合は、$ fのすべての出現箇所を二重引用符で囲む必要があります。ただし、スクリプトで定義されているため、実際には安全です。やめる。)
最後にecho "">$OUTPUT
、ループオーバーファイルの上部近くに、毎回出力ファイルを消去します(つまり、最後に、最後の.textileファイルのみが含まれます)。これはループの前に移動する必要があります。ここでの目的がファイルの先頭に1行の空白行を配置することなのか、ファイル間に3行の空白行(および最初に1行、最後に2行)を配置することなのかわからないため、正確にはわかりません。適切な交換はです。とにかく、これらの問題をすべて修正した後、私ができることは次のとおりです。
#!/bin/sh
OUTPUT="../best_practices.textile"
FILES=(../best-practices/*.textile)
: >"$OUTPUT"
for f in "${FILES[@]}"
do
echo "Processing $f file..."
echo >>"$OUTPUT"
while IFS='' read -r line; do
printf "%s\n" "$line">>"$OUTPUT"
done <"$f"
echo >>"$OUTPUT"
echo >>"$OUTPUT"
done