
Я пытаюсь выполнить несколько команд для найденных мной объектов. Как мне этого добиться?
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