Я пытаюсь выполнить несколько команд для вещей, которые я нашел, как я могу добиться этого?
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
между ними вынуждает тестовое состояние "false", а -o
заставляет вычислять следующее выражение (второе -exec
) из-за -false
.
От man find
:
expr1 expr2
Два выражения подряд взяты, чтобы быть объединенными с подразумеваемым "и"; expr2 не оценивается, если expr1 имеет значение false.expr1 -a expr2
То же, что expr1 expr2.expr1 -o expr2
Или же; expr2 не оценивается, если expr1 имеет значение true.
Если вам не важно, что cmd1 может предотвратить запуск cmd2 из-за кода ошибки 0
:
find . -exec cmd1 \; -exec cmd2 \;
Единственный надежный способ заставить обе команды всегда выполняться, это заставить find
вызывать оболочку, которая впоследствии будет запускать команды в последовательности:
find . -exec bash -c 'cmd1; cmd2' filedumper {} \;
Если вы не против создать скрипт, который выполняет 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 не может вызывать функции оболочки, которые вы определили в вашем скрипте.
Я пробовал оба предыдущих решения без особой удачи. Этот работал хорошо для меня:
$ 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