Как использовать канал в параметре exec для команды поиска?

Я пытаюсь создать команду find для обработки группы файлов в каталоге с использованием двух разных исполняемых файлов. К сожалению, -exec при поиске не позволяет использовать канал или даже \|, потому что оболочка сначала интерпретирует этот символ.

Вот что я пытаюсь сделать (что не работает, потому что канал завершает команду поиска):

find /path/to/jpgs -type f -exec jhead -v {} | grep 123 \; -print

person hoyhoy    schedule 15.09.2008    source источник


Ответы (6)


Попробуй это

find /path/to/jpgs -type f -exec sh -c 'jhead -v {} | grep 123' \; -print

В качестве альтернативы вы можете попытаться встроить оператор exec в сценарий sh, а затем выполнить:

find -exec some_script {} \;
person Martin Marconcini    schedule 15.09.2008

Немного другим подходом было бы использование xargs:

find /path/to/jpgs -type f -print0 | xargs -0 jhead -v | grep 123

который я всегда находил немного проще для понимания и адаптации (аргументы -print0 и -0 необходимы для работы с именами файлов, содержащими пробелы)

Это может (не проверено) быть более эффективным, чем использование -exec, потому что оно передает список файлов в xargs, а xargs гарантирует, что командная строка jhead не станет слишком длинной.

person Palmin    schedule 15.09.2008
comment
Проблема с использованием xargs здесь заключается в том, что мне нужно имя файла, которое соответствует. Эта команда находит совпадения, но я не знаю, какой файл соответствует. - person hoyhoy; 16.09.2008

С -exec вы можете запускать только один исполняемый файл с некоторыми аргументами, а не произвольные команды оболочки. Чтобы обойти это, вы можете использовать sh -c '<shell command>'.

Обратите внимание, что использование -exec довольно неэффективно. Для каждого найденного файла команду необходимо выполнить снова. Было бы более эффективно, если бы вы могли избежать этого. (Например, переместив grep за пределы -exec или передав результаты find в xargs, как это предлагается Palmin.)

person mweerden    schedule 15.09.2008
comment
Другой способ избежать неэффективности множественных процессов в общем случае — использовать xargs. Если вам нужны отдельные процессы, вы можете использовать опцию -i. Я считаю, что xargs больше соответствует модели Unix. - person Jon Ericson; 18.09.2008
comment
AOL при использовании xargs. mweerden, возможно, вам следует изменить свой последний абзац, приняв во внимание существование xargs. Также обратите внимание на флаг -0, который присутствует как в find, так и в xargs. - person tzot; 12.10.2008

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

for i in dist/*.jar; do echo ">> $i"; jar -tf "$i" | grep BeanException; done
person Dimitar    schedule 27.02.2011

Поскольку это выводит список, вы бы не:

find /path/to/jpgs -type f -exec jhead -v {} \; | grep 123

or

find /path/to/jpgs -type f -print -exec jhead -v {} \; | grep 123

Поместите свой grep на результаты поиска -exec.

person Xetius    schedule 15.09.2008
comment
Это не работает, потому что мне нужно, чтобы -print работал. Если grep возвращает успех, find печатает имя файла, иначе нет. - person hoyhoy; 15.09.2008

Есть еще один способ сделать это, но это тоже довольно гетто.

Используя опцию оболочки extquote, вы можете сделать что-то подобное, чтобы найти содержимое 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.

person linuxgeek    schedule 01.02.2018