![Git Bash でファイル名のスペースを処理する方法](https://rvso.com/image/1558675/Git%20Bash%20%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%E3%81%AE%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%82%92%E5%87%A6%E7%90%86%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95.png)
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
の出力に対しては、決して実行しないでください。find
ls
この記事なぜこれが問題なのか、そしてそれを解決するために何ができるのかについて詳しくは、こちらをご覧ください。
つまり、Bash は引数を空白で分割します。a
、という 3 つのファイルがあるとするfoo bar
とb
、この行は次のように評価されます。
for logfile in a foo bar b; do
明らかに、Bash は、、、logfile
を設定しますが、これは希望どおりではありません。 への入力を手動で指定できる場合は、これらのファイル名を引用符で囲むことで問題を解決できます。a
foo
bar
b
for
これを自動的に行うための解決策は、これらのファイル名を文字で区切りNUL
(オプションが行うこと-print0
)、その文字に基づいて出力を再度分割することです( inが行うNUL
こと)。-d ''
read