Як використовувати конвеєр у параметрі exec для команди find?


77

Я намагаюся побудувати команду find, щоб обробити купу файлів у каталозі за допомогою двох різних виконуваних файлів. На жаль, -execу пошуку не дозволяє використовувати конвеєр або навіть \|тому, що оболонка спочатку інтерпретує цей символ.

Ось конкретно те, що я намагаюся зробити (що не працює, оскільки труба закінчує команду find):

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

Відповіді:


87

Спробуйте це

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

Крім того, ви можете спробувати вбудувати свій оператор exec всередину sh-сценарію, а потім зробити:

find -exec some_script {} \;

15

Дещо іншим підходом було б використання xargs:

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

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

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


4
Проблема використання xargs тут полягає в тому, що мені потрібно ім’я файлу, яке відповідає. Ця команда дійсно знаходить збіги, але я не знаю, який файл відповідає.
hoyhoy

4

За допомогою -execви можете запустити лише один виконуваний файл з деякими аргументами, а не довільними командами оболонки. Щоб обійти це, ви можете використовувати sh -c '<shell command>'.

Зауважимо, що використання -execвкрай неефективно. Для кожного знайденого файлу команда повинна бути виконана знову. Було б ефективніше, якщо ви зможете цього уникнути. (Так , наприклад, шлях переміщення grepза межі -execабо конвеєра результатів , findщоб xargsяк це було запропоновано Пальмін .)


1
Іншим способом уникнути багаторазової неефективності процесу в загальному випадку є використання xargs. Якщо вам трапляються окремі процеси, ви можете скористатися опцією -i. Я вважаю, що xargs більше відповідає моделі Unix.
Джон Еріксон,

1
AOL на використанні ксарг. mweerden, можливо, вам слід змінити свій останній абзац, беручи до уваги існування xargs. Також зверніть увагу на прапор -0, який існує в обох findта xargs.
tzot

3

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

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

1

Оскільки це виводить список, ви б не:

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

або

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

Покладіть свою grep на результати пошуку -exec.


Це не працює, тому що мені потрібен -print для роботи. Якщо grep повертає успіх, тоді find друкує ім'я файлу, інакше ні.
hoyhoy

0

Існує інший спосіб зробити це, але це також досить гетто.

Використовуючи опцію оболонки 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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.