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

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

Я пытаюсь выполнить несколько команд для найденных мной объектов. Как мне этого добиться?

find . -exec cmd1; cmd2

похоже, не работает; вместо этого он запускает cmd2 после того, как cmd1 был выполнен для каждого файла.

решение1

В этой демонстрации я буду использовать 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 истинно.

решение2

Если вас не волнует, что cmd1 может помешать запуску cmd2 из-за кода ошибки 0:

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

Единственный надежный способ заставить обе команды всегда выполнять это — вызвать findоболочку, которая последовательно выполнит команды:

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

решение3

Если вы не против создания скрипта, который выполняет cmd1 и cmd2, то вот он:

find . -exec myscript {} \;

или

find . -exec myscript {} +

Используйте \; или + в зависимости от того, может ли myscript обрабатывать более одного файла одновременно (становится затруднительно, если в именах файлов есть пробелы и т. д.).

По моему опыту, включение того, что вы делали, в сценарий почти всегда того стоило. Если вам пришлось сделать это один раз, вам придется сделать это снова.

Но есть один хитрый трюк: поместить находкувнутрисценарий:

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

Затем myscript работает с любыми файлами, которые вы указываете в качестве аргументов для работы, но если вы не указываете никаких аргументов, он запускает find из текущего каталога, а затем вызывает себя для найденных файлов. Это позволяет обойти тот факт, что find -exec не может вызывать функции оболочки, которые вы определили в своем скрипте.

решение4

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

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

Связанный контент