Questa è una limitazione di find
. Lo standard POSIX specifica che lo stato di ritorno di find
è 0 a meno che non si sia verificato un errore durante l'attraversamento le directory; lo stato di ritorno dei comandi eseguiti non vi entra.
Puoi fare in modo che i comandi scrivano il loro stato su un file o su un descrittore:
find_status_file=$(mktemp findstatus)
: >"$find_status_file"
find … -exec sh -c 'trap "echo \$?" EXIT; invalid_command "$0"' {} \;
if [ -s "$find_status_file" ]; then
echo 1>&2 "An error occurred"
fi
rm -f "$find_status_file"
Un altro metodo, come te scoperto , usa xargs. I comandi xargs
elaborano sempre tutti i file, ma restituiscono lo stato 1 se uno qualsiasi dei comandi restituisce uno stato diverso da zero.
find … -print0 | xargs -0 -n1 invalid_command
Ancora un altro metodo consiste nel rifuggire find
e utilizzare invece il globbing ricorsivo nella shell: **/
indica qualsiasi profondità di sottodirectory. Ciò richiede la versione 4 o successiva di bash; macOS è bloccato alla versione 3.x quindi dovresti installarlo da una collezione di porte. Usa set -e
per fermare lo script sul primo comando che restituisce uno stato diverso da zero.
shopt -s globstar
set -e
for x in **/*.xml; do invalid_command "$x"; done
Attenzione, da bash 4.0 a 4.2, funziona ma attraversa collegamenti simbolici a directory, che di solito non sono desiderabili.
Se usi zsh invece di bash, il globbing ricorsivo funziona fuori dalla scatola senza trucchi. Zsh è disponibile di default su OSX / macOS. In zsh, puoi solo scrivere
set -e
for x in **/*.xml; do invalid_command "$x"; done