![Как обрабатывать пробелы в именах файлов в Git Bash](https://rvso.com/image/1558675/%D0%9A%D0%B0%D0%BA%20%D0%BE%D0%B1%D1%80%D0%B0%D0%B1%D0%B0%D1%82%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D0%BF%D1%80%D0%BE%D0%B1%D0%B5%D0%BB%D1%8B%20%D0%B2%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B0%D1%85%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%20%D0%B2%20Git%20Bash.png)
Я написал следующий скрипт для запуска в Git Bash под Windows 7:
#!/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
with -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
, foo bar
и b
, тогда строка будет вычисляться как:
for logfile in a foo bar b; do
Очевидно, Bash установит logfile
, a
, foo
, bar
и b
, что не то, что вы хотели. Если бы вы могли вручную указать ввод for
, вы бы заключили эти имена файлов в кавычки, чтобы решить проблему.
Чтобы сделать это автоматически, решением будет разграничить эти имена файлов символом NUL
(что и -print0
делает опция), а затем снова разделить вывод на основе этого NUL
символа (что и делает опция -d ''
in read
).