Як виконати декілька команд при використанні пошуку?


57

Я намагаюся запустити кілька команд над знайденими речами, як це досягти?

find . -exec cmd1; cmd2

здається, не працює; він замість цього запускає cmd2 після того, як cmd1 був виконаний у кожному файлі.

Відповіді:


40

У цій демонстрації я буду використовувати sh -c 'echo first; false'(або true) для першого -exec. Це дасть деякий вихід, а також матиме вибраний ефект вихідного коду. Потім echo secondбуде використовуватися для другого. Припустимо, що в поточному каталозі є один файл.

$ find . -type f -exec sh -c 'echo first; false' \; -exec echo second \;
first
$ find . -type f -exec sh -c 'echo first; true' \; -exec echo second \;
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second

Справжня команда такого типу виглядатиме так:

find . -type f \( -exec command1 \; -false -o -exec command2 \; \)

У другому наборі дужки, що уникнули, групують два -execпункти. -falseМіж ними змушує тест стану до «помилковим» , і -oпризводить до того , наступного виразу (другий -exec) , щоб оцінити через -false.

Від man find:

expr1 expr2
Два вирази підряд приймаються до об'єднаних "та"; expr2 не оцінюється, якщо expr1 хибний.

expr1 -a expr2
Те саме, що expr1 expr2.

expr1 -o expr2
Або; expr2 не оцінюється, якщо expr1 вірно.


Ага так, я про це забув -o.
Ігнасіо Васкес-Абрамс

32

Якщо вам не важливо, чи cmd1 не зможе завадити запуску cmd2 через код помилки 0:

find . -exec cmd1 \; -exec cmd2 \;

Єдиний надійний спосіб змусити обидві команди завжди виконувати це - findвикликати оболонку, яка згодом виконуватиме команди послідовно:

find . -exec bash -c 'cmd1; cmd2' filedumper {} \;

2

Якщо ви не проти створити сценарій, який робить cmd1 та cmd2, то це просто так:

find . -exec myscript {} \;

або

find . -exec myscript {} +

Використовувати \; або + залежно від того, чи може скрипт обробляти більше одного файлу одночасно (стає волохатим, якщо є пробіли у назви файлів тощо).

Вкладати те, що ви робили за сценарієм, на мій досвід, майже завжди того вартувало. Якщо вам доведеться це зробити один раз, вам доведеться це зробити ще раз.

Але акуратний трюк - ввести знахідку всередині сценарію:

if [ $# -gt 0 ]; then
    for each; do
        touch $each
    done
else
    find . -exec $0 {} +
fi

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


0

Я намагався обидва попередніх рішення без особливої ​​удачі. Цей прекрасно працював для мене:

$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done

Це не спрацює, якщо список файлів занадто великий.
Олексій

-3

спробуйте команду:

sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l

4
Е, це не дуже гарна ідея. *У -execчастині буде розширюватися на всі файли в поточному каталозі. Особливо при бігу як sudo.
slhck
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.