62 votes

Comment exécuter plusieurs commandes en utilisant find ?

J'essaie d'exécuter des commandes multiples sur des éléments que j'ai trouvés, comment puis-je y parvenir ?

find . -exec cmd1; cmd2

ne semble pas fonctionner ; il exécute plutôt cmd2 après que cmd1 ait été exécuté sur chaque fichier.

41voto

Damian Powell Points 315

Dans cette démonstration, je vais utiliser sh -c 'echo first; false' (ou true ) pour le premier -exec . Cela donnera une certaine sortie et aura également l'effet du code de sortie sélectionné. Puis echo second sera utilisé pour le second. Supposons qu'il y ait un fichier dans le répertoire courant.

$ 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

Une vraie commande de ce type ressemblerait à ceci :

find . -type f \( -exec command1 \; -false -o -exec command2 \; \)

Dans le deuxième ensemble, les parenthèses échappées regroupent les deux -exec clauses. Le site -false entre eux force l'état du test à "false" et la -o entraîne l'expression suivante (la deuxième -exec ) à évaluer en raison de la -false .

De man find :

expr1 expr2
Deux expressions dans une rangée sont considérées comme jointes par un sous-entendu. "et" implicite ; expr2 n'est pas évaluée si expr1 est fausse.

expr1 -a expr2
Identique à expr1 expr2.

expr1 -o expr2
Ou ; expr2 n'est pas évalué si expr1 est vrai.

37voto

Si vous ne vous souciez pas que cmd1 puisse empêcher cmd2 d'être exécuté à cause du code d'erreur 0 :

find . -exec cmd1 \; -exec cmd2 \;

La seule façon fiable d'obtenir que les deux commandes s'exécutent toujours ainsi est d'avoir find invoque un Shell qui exécutera ensuite les commandes en séquence :

find . -exec bash -c 'cmd1; cmd2' filedumper {} \;

2voto

mza Points 21

Si ça ne vous dérange pas de faire un script qui fait cmd1 et cmd2, alors c'est juste ça :

find . -exec myscript {} \;

o

find . -exec myscript {} +

Utilisez \ ; ou + selon que myscript peut ou non gérer plus d'un fichier à la fois (cela devient délicat s'il y a des espaces dans les noms de fichiers, etc).

Mettre ce que vous faisiez dans un script, dans mon expérience, a presque toujours valu la peine. Si vous devez le faire une fois, vous devrez le faire à nouveau.

Mais une astuce astucieuse consiste à mettre la trouvaille à l'intérieur de le script :

if [ $# -gt 0 ]; then
    for each; do
        touch $each
    done
else
    find . -exec $0 {} +
fi

Ensuite, myscript travaille sur les fichiers que vous lui donnez comme arguments, mais si vous ne lui donnez pas d'arguments, il lance find à partir du répertoire courant, et s'appelle lui-même sur les fichiers trouvés. Ceci contourne le fait que find -exec ne peut pas appeler les fonctions Shell que vous avez définies dans votre Shell.

0voto

Hans Points 242

J'ai essayé les deux solutions précédentes sans grand succès. Celle-ci a bien fonctionné pour moi :

$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done

-3voto

Saptak Das Points 1

Essayez la commande :

sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X