Git Bash でファイル名のスペースを処理する方法

Git Bash でファイル名のスペースを処理する方法

Windows 7 の Git Bash で実行するために次のスクリプトを作成しました。

#!/usr/bin/env sh
for logfile in `find -name "*.log" -o -name "*.err" -o -name "*.out"`
do
    echo $logfile
    grep "api/" "$logfile"
done

問題は、ファイル名にスペースが含まれていると grep が機能しなくなることです。二重引用符で対処できると思っていましたが、うまくいきませんでした。

アイデアは?

答え1

解決策1

最も近い解決策は、findを使用し-print0、 で出力を読み取ることですwhile read …

find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do
    ...

"$logfile"変数を使用する場合は常に引用符を使用して引用符で囲む必要があります。

解決策2

find別の解決策としては、まったく使用せず、grep複数のファイルで実行することです。

shopt -s nullglob
shopt -s globstar
grep "api/" **/*.log **/*.err **/*.out

ここで、globstarは を持つディレクトリの再帰的な一致を有効にします。これらのファイル拡張子のいずれかが存在しない場合にエラーが発生しないようにするには、**を設定する必要があります。nullglob

ただし、コマンドライン引数の最大長に達する可能性があるため、これは限られたファイルセットに対してのみ機能します。

なぜエラーが発生するのでしょうか?

(または、または空白を含むファイル名を出力するその他の関数)forの出力に対しては、決して実行しないでください。findlsこの記事なぜこれが問題なのか、そしてそれを解決するために何ができるのかについて詳しくは、こちらをご覧ください。

つまり、Bash は引数を空白で分割します。a、という 3 つのファイルがあるとするfoo barb、この行は次のように評価されます。

for logfile in a foo bar b; do

明らかに、Bash は、、、logfileを設定しますが、これは希望どおりではありません。 への入力を手動で指定できる場合は、これらのファイル名を引用符で囲むことで問題を解決できます。afoobarbfor

これを自動的に行うための解決策は、これらのファイル名を文字で区切りNUL(オプションが行うこと-print0)、その文字に基づいて出力を再度分割することです( inが行うNULこと)。-d ''read

関連情報