Exécuter des commandes sur plusieurs fichiers : find -exec vs find xargs

De Linux Server Wiki
Révision datée du 29 juillet 2022 à 11:07 par Pfoo (discussion | contributions)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche


find -exec

find \;

find . [args] -exec [cmd] {} \;
find . -name \*.html -type f -exec grep -Hn 'pattern' {} \;
  • {} contiendra le résultat trouvé par find
  • \; signifie que pour chaque résultat trouvé par find, la commande (grep dans l'exemple) sera exécuté une fois sur le résultat trouvé
    • Donc si find trouve 4000 fichiers, la commande (grep ici) sera exécutée 4000 fois.

find \+

find . [args] -exec [cmd] {} \+
find . -name \*.html -type f -exec grep -Hn 'pattern' {} \+
  • {} contiendra le résultat trouvé par find
  • \+ tous les résultats trouvés par find sont mergés et la commande (grep ici) n'est exécutée qu'une seule fois avec tous les résultats de find.
    • Inconvénient possible : si find trouve beaucoup de résultat, vous allez finir par atteindre ARG_LIMIT

find | xargs

xargs avec -n1

find .[args] -print0 | xargs -0 -n1 [cmd]
find . -name \*.html -type f -print0 | xargs -0 -n1 grep -Hn 'pattern'
  • -print0 spécifie à find qu'il doit retourner les résultats à la sortie standard, séparés par le caractère ASCII nul \000
  • -0 spécifie à xargs que l'entrée qu'il reçoit est séparé par le caractère ASCII nul \000
  • -n1 demande à xargs d’exécuter la commande avec un seul argument à la fois (dans le cas présent, avec un seul fichier trouvé par find). Cela est similaire au \; de -exec. La commande est donc exécutée autant de fois qu'il y a de fichier trouvé par find.
    • On peut modifier 1 par n'importe quelle valeur

xargs sans -n

find . [args] -print0 | xargs -0 [cmd]
find . -name \*.html -type f -print0 | xargs -0 grep -Hn 'pattern'
  • -print0 spécifie à find qu'il doit retourner les résultats à la sortie standard, séparés par le caractère ASCII nul \000
  • -0 spécifie à xargs que l'entrée qu'il reçoit est séparé par le caractère ASCII nul \000
  • Quand on ne spécifie pas -nINT, xargs utilise le défaut -n5000. Cela signifie donc que la commande est exécutée avec 5000 arguments maximums, donc dans le cas présent, avec 5000 fichiers à la fois (puis la commande est exécutée une seconde fois avec les 5000 fichiers suivants, etc). Cela est similaire avec le +; de -exec, néanmoins sans risque de dépasser ARG_LIMIT, ni une limite arbitraire fixée par la commande que vous exécutez.

caractère ASCII nul \000

Le caractère ASCII nul \000 est une bonne manière de gérer les fichiers contenants des espaces You have to use both or neither of them. The advantage is that all results will be handed over to xargs as a single string without newline separation. NUL charater separation is a way to escape files which also contain spaces in their filenames.

performances

Globalement, xargs -n1 est légèrement plus rapide que \;, et xargs -n5000 a une vitesse similaire à \+

Notez que xargs peut se paralléliser avec -PINT (généralement -P4 ou -P8 selon le nombre de cœur de votre processeur), ce qui en augmentera les performances que ce soit avec -n1 ou sans.
Rappelez vous que l'intérêt de paralléliser une commande traitant des fichiers n'augmentera les performances que si vous devez appliquer une commande à un nombre important de petits fichiers. Si vous traitez de gros fichiers, la vitesse de votre disque deviendra le facteur limitant et vous perdrez très vite les bénéfices de la parallélisation.

Différence à noter

  • find -exec retourne l'exit-code de find et pas celui de la sous-commande.
  • find | xargs retourne l'exit-code de la sous-commande.