Как выйти из find -exec, если он не работает на одном из файлов

Я хочу запустить команду

find some/path -exec program \{} \; 

но я хочу, чтобы команда find вышла, как только команда

 program \{}

не удается найти ни один из найденных файлов.

Есть ли простой способ сделать это?

Ответы

Ответ 1

В дополнение к другим тонким ответам GNU find (по крайней мере) имеет предикат -quit:

find path -other -predicates \( -exec cmd {} \; -o -quit \)

Предикат -quit конечно нестандартный и не существует в поиске BSD.

Ответ 2

Я думаю, что невозможно достичь того, чего вы хотите, только с find -exec.

Ближайшей альтернативой было бы сделать pipe find до xargs, например:

find some/path -print0 | xargs -0 program

или

find some/path -print0 | xargs -0L1 program

Это прекратится, если программа завершится с ненулевым статусом выхода

  • используется print0, так что файлы с символами новой строки в их именах могут обрабатываться
  • -0 необходимо, когда используется -print0
  • L1 сообщает программе xargs выполнить программу с одним аргументом за раз (по умолчанию нужно добавить все аргументы в одно исполнение программы)

Если у вас есть только правильные имена файлов, вы можете упростить это:

find some/path | xargs program

или

find some/path | xargs -L1 program

Наконец, если программа принимает более одного аргумента, вы можете использовать -i в сочетании с {}. Например.

find some/path | xargs -i program param1 param2 {} param4

Ответ 3

Вы можете передать вывод из find в другой подпроцесс и использовать while/break:

find some/path | while read f
do
    program $f
    if [ $? -ne 0 ]
    then
        break
    fi
done

Ответ 4

% _find_trap() {
>   _find_pid="${1}" ; _find_ops="${2}" ; _find_trigger="${3}"
>   shift 3 && set -- "${@}" 
>   trap 'kill -s INT "-${_find_pid}" \
>     unset _find_pid _find_ops _find_trigger ; set - \
>     1>&2 printf "%s" "find killed due to trap" \
>     exit [CODE] ' TRAP
>  while { sh -c "${_find_ops} ${@}"} {
>    [ "${_find_trigger}" ] && { kill -s TRAP "-${_find_pid}" ; break ; }
>    ...
>  }
> export -f _find_trap ; find . -execdir _find_trap \"$$\" \"${cmds}\" \
>   \"${testable_trigger}\" "{}" +

Ответ 5

Вот мой пример для "системы сборки", которая останавливается после попадания первой ошибки компилятора (на основе ответа Коджиро, который не работал у меня):

(Необходимость в скопированных скобках реальна. Я знаю, что это больно.)

find -name '*.cpp' \( -print -a -exec g++ -c {} \; -o -quit \)

Я хочу создать статическую библиотеку в основном всех файлов С++, расположенных в текущем каталоге и ниже.

Перед запуском компилятора я хочу иметь файл -print -ed, затем -exec -ed, но когда он терпит неудачу (и оставляет ошибки на stderr, он должен -quit.

-a похож на &&, а -o похож на || в оболочке или C.

Без круглых скобок GNU находит "оптимизирует" запрос, сначала попробовав наиболее вероятное условие, которое - я думаю - -quit.