вырваться из-за сбоя -exec


14

Есть ли способ написать findтак, чтобы он сломался, если одна из -execопераций не выполняется для файла?

Например ( javacудобно использовать в качестве программы, которая может возвращать код выхода 1 для некоторых файлов и ни по какой другой причине):

$ echo "public classXX A{}" >> A.java
$ echo "public class B{}" >> B.java
$ find . -iname \*.java -exec javac {} \;
./A.java:1: error: class, interface, or enum expected
public classXX A{}
       ^
1 error

В приведенном выше примере, хотя завершение работы execнад файлом A.java(и возвращение кода выхода равным 1), findкоманда продолжила и скомпилировал файл B.java. Есть ли способ вырваться findили я должен использовать какую-то форму forвместо?

Моя версия найти:

$ find -version  | head -1
find (GNU findutils) 4.4.2

Ответы:


5

Я думаю...

find ... -exec sh -c 'cmd "$0" || kill $PPID' \{\} \;

... должен сделать трюк для любого find.


Спасибо, Жиль. Что делает $0?
mikeserv

1
$0является первым аргументом sh -c( $1является вторым и т. д.) - обычно это имя исполняемой программы, но здесь вы выполняете фрагмент и передаете имя обрабатываемого файла, что $0имеет некоторый смысл (например, вы легко видите это в ps). Есть школа мысли (к которой я, очевидно, не принадлежу), которая утверждает, что она $0всегда должна быть исполняемой, и вы должны написать sh -c 'cmd "$1" …' sh {}или что-то подобное.
Жиль "ТАК - перестать быть злым"

@ Жиль - довольно гладко. Большое спасибо. Я понял это в машине по дороге в дошкольное учреждение, но мне пришлось подумать об этом несколько минут. Это умно - я собираюсь использовать это. Что мне на самом деле понравилось, так это редактирование, которое я запомнил, прочитав Стефана в одном из ваших собственных постов, в котором он добавил find-sh $0в конце findутверждения. Это кажется более полезным, на мой взгляд, хотя я думаю, что именно то, что вам нужно в долгосрочной перспективе, имеет наибольшее значение.
mikeserv

Это не работает для случая выше. После сбоя find . -iname \*.java -exec sh -c 'javac "${0}" || kill '$$ {} \;файла A.javaи, тем не менее, файл B.java компилируется.
Маркус Юний Брутус

@MarcusJuniusBrutus - я исправил это. Я должен был увидеть ваш комментарий ранее. Опять извините.
mikeserv

4

По крайней мере, с GNU findвы можете использовать:

find ... -exec ... -o -quit

Кажется, у меня возникают проблемы с разъяснением того, где исполняемый файл останавливается и начинается -o. И то find . -iname \*.java -exec javac {} -o -quit \;и другое find . -iname \*.java -exec javac {} \; -o -quit \;терпит неудачу (по-разному)
Маркус Юний Брут

@MarcusJuniusBrutus \;необходим в и из -exec(т.е. раньше -o -quitв этом случае), но может быть больше нигде.
Хауке Лагинг

2
Использование -exec ... -o -quitне работает для меня. Он не обрабатывает никаких файлов. Однако эта линия работает: find . -iname \*.java -not -exec javac '{}' \; -quit: -quitвызывается , если -execложно, то есть. возвращается с ненулевым
Саванто

find . -iname \*.java -exec javac {} \; -o -quitтоже не удается обработать любые файлы. Странно find . -iname \* -exec echo 'foo' \; -o -quit ли "обрабатывать" файлы.
Маркус Юний Брут

0

Обратитесь к своему findруководству. Ответ @ Хауке побудил меня посмотреть, а в поиске QNX есть -abortопция, которая похожа на -quitопцию GNU . Это работает для меня, если я использую \(и \)группировать выражения:

find . -mtime -4 -name <pattern> \( -exec my_cmd {} \; -o  -abort \) 

Примечание: без паренов он прерывает первый файл.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.