Назад | Перейти на главную страницу

Как я могу обрабатывать пробелы в именах файлов при использовании xargs для результатов поиска?

Одна из моих распространенных практик - выполнить greps для всех файлов определенного типа, например, найти все файлы HTML, в которых есть слово "rumpus". Для этого я использую

find /path/to -name "*.html" | xargs grep -l "rumpus"

Время от времени, find вернет файл с пробелом в его имени, например my new file.html. когда xargs передал это grepоднако я получаю такие ошибки:

grep: /path/to/bad/file/my: No such file or directory
grep: new: No such file or directory
grep: file.html: No such file or directory

Я вижу, что здесь происходит: либо труба, либо xargs обрабатывает пробелы как разделители между файлами. Хотя хоть убей, я не могу понять, как предотвратить такое поведение. Можно ли это сделать с find + xargs? Или мне нужно использовать совершенно другую команду?

Использовать

find ... -print0 | xargs -0 ...

например

find /path/to -name "*.html"  -print0 | xargs -0  grep -l "rumpus"

со страницы руководства по поиску

-print0
          True; print the full file name on the standard  output,  followed
          by  a  null  character  (instead  of  the  newline character that
          ‘-print’ uses).  This allows file names that contain newlines  or
          other  types  of  white space to be correctly interpreted by pro-
          grams that process the find output.  This option  corresponds  to
          the ‘-0’ option of xargs.

Вам не нужно использовать xargs, так как найти может сам выполнять команды. При этом вам не нужно беспокоиться о том, что оболочка интерпретирует символы в имени.

find /path/to -name "*.html" -exec grep -l "rumpus" '{}' +

со страницы руководства по поиску

-exec команда {} +
Этот вариант действия -exec запускает указанную команду для выбранных файлов, но командная строка строится путем добавления каждого выбранного имени файла в конце; общее количество вызовов команды будет намного меньше, чем количество совпадающих файлов. Командная строка строится почти так же, как xargs строит свои командные строки. В команде разрешен только один экземпляр "{}". Команда выполняется в стартовом каталоге.

Если версии find и xarg в вашей системе не поддерживают -print0 и -0 переключатели (например, AIX find и xargs), вы можете использовать это:

find /your/path -name "*.html" | sed 's/ /\\ /g' | xargs grep -l "rumpus"

Здесь sed позаботится об экранировании пробелов для xargs.