Как мне использовать канал в параметре exec для команды find?
Вопрос
Я пытаюсь создать команду find для обработки группы файлов в каталоге, используя два разных исполняемых файла.К сожалению, -exec
on find не позволяет использовать pipe или даже \|
потому что оболочка сначала интерпретирует этот символ.
Вот конкретно, что я пытаюсь сделать (что не работает, потому что канал завершает команду find):
find /path/to/jpgs -type f -exec jhead -v {} | grep 123 \; -print
Решение
Попробуй это
find /path/to/jpgs -type f -exec sh -c 'jhead -v {} | grep 123' \; -print
В качестве альтернативы вы могли бы попытаться встроить свой оператор exec в скрипт sh, а затем выполнить:
find -exec some_script {} \;
Другие советы
Несколько иным подходом было бы использование xargs:
find /path/to/jpgs -type f -print0 | xargs -0 jhead -v | grep 123
который я всегда находил немного более легким для понимания и адаптации (аргументы -print0 и -0 необходимы для работы с именами файлов, содержащими пробелы)
Это мог бы (не тестировалось) более эффективно, чем использование -exec, потому что это передаст список файлов в xargs, а xargs гарантирует, что командная строка jhead не станет слишком длинной.
С -exec
вы можете запустить только один исполняемый файл с некоторыми аргументами, а не произвольные команды оболочки.Чтобы обойти это, вы можете использовать sh -c '<shell command>'
.
Обратите внимание, что использование -exec
это довольно неэффективно.Для каждого найденного файла команда должна быть выполнена повторно.Было бы эффективнее, если бы вы могли избежать этого.(Например, перемещая grep
за пределами -exec
или передавать результаты find
Для xargs
как было предложено Пальмин.)
Используя find
команда для такого типа задач, возможно, не самая лучшая альтернатива.Я часто использую следующую команду для поиска файлов, содержащих запрошенную информацию:
for i in dist/*.jar; do echo ">> $i"; jar -tf "$i" | grep BeanException; done
Поскольку это выводит список, не могли бы вы :
find /path/to/jpgs -type f -exec jhead -v {} \; | grep 123
или
find /path/to/jpgs -type f -print -exec jhead -v {} \; | grep 123
Поместите свой grep в результаты find -exec.
Есть какой-то другой способ, которым вы можете это сделать, но это тоже довольно гетто.
Используя опцию командной строки extquote, вы можете сделать что-то похожее на это, чтобы заставить find exec использовать материал, а затем передать его в sh.
root@ifrit findtest # find -type f -exec echo ls $"|" cat \;|sh
filename
root@ifrit findtest # find -type f -exec echo ls $"|" cat $"|" xargs cat\;|sh
h
Я просто решил добавить это, потому что, по крайней мере, в том виде, в каком я это визуализировал, это было ближе к первоначальному вопросу OP об использовании каналов в exec.