Я намагаюся запустити кілька команд над знайденими речами, як це досягти?
find . -exec cmd1; cmd2
здається, не працює; він замість цього запускає cmd2 після того, як cmd1 був виконаний у кожному файлі.
Я намагаюся запустити кілька команд над знайденими речами, як це досягти?
find . -exec cmd1; cmd2
здається, не працює; він замість цього запускає cmd2 після того, як cmd1 був виконаний у кожному файлі.
Відповіді:
У цій демонстрації я буду використовувати 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 вірно.
Якщо вам не важливо, чи cmd1 не зможе завадити запуску cmd2 через код помилки 0
:
find . -exec cmd1 \; -exec cmd2 \;
Єдиний надійний спосіб змусити обидві команди завжди виконувати це - find
викликати оболонку, яка згодом виконуватиме команди послідовно:
find . -exec bash -c 'cmd1; cmd2' filedumper {} \;
Якщо ви не проти створити сценарій, який робить 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 не може викликати функції оболонки, визначені у вашому сценарії.
Я намагався обидва попередніх рішення без особливої удачі. Цей прекрасно працював для мене:
$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done
спробуйте команду:
sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l
*
У -exec
частині буде розширюватися на всі файли в поточному каталозі. Особливо при бігу як sudo
.
-o
.