Lequel est le plus efficace sur un très grand ensemble de fichiers et doit être utilisé?
find . -exec cmd {} +
ou
find . | xargs cmd
(Supposons qu'il n'y ait pas de personnages amusants dans les noms de fichiers)
Lequel est le plus efficace sur un très grand ensemble de fichiers et doit être utilisé?
find . -exec cmd {} +
ou
find . | xargs cmd
(Supposons qu'il n'y ait pas de personnages amusants dans les noms de fichiers)
Réponses:
La différence de vitesse sera insignifiante.
Mais vous devez vous assurer que:
Votre script ne supposera pas qu'aucun fichier n'aura d'espace, de tabulation, etc. dans le nom de fichier; la première version est sûre, la seconde ne l'est pas.
Votre script ne traitera pas un fichier commençant par " -
" comme une option.
Donc, votre code devrait ressembler à ceci:
find . -exec cmd -option1 -option2 -- {} +
ou
find . -print0 | xargs -0 cmd -option1 -option2 --
La première version est plus courte et plus facile à écrire car vous pouvez ignorer 1, mais la deuxième version est plus portable et plus sûre, car " -exec cmd {} +
" est une option relativement nouvelle dans GNU findutils (depuis 2005, de nombreux systèmes en cours d'exécution ne l'auront pas encore) et c'était buggy récemment . De plus, beaucoup de gens ne le savent pas " -exec cmd {} +
", comme vous pouvez le voir dans d'autres réponses.
exec
affichera les résultats tels qu'ils sont trouvés, ce xargs
qui, semble-t-il, attendra que tout le répertoire soit recherché avant d'écrire dans stdout. Si vous essayez ceci sur un grand répertoire et qu'il semble que cela xargs
ne fonctionne pas, la patience est recommandée.
-print0
find renvoie les noms de fichiers séparés par une nouvelle ligne, mais une nouvelle ligne peut également faire partie d'un nom de fichier, ce qui le rend ambigu. L'octet 0 ne peut pas, c'est donc un séparateur sûr. Oui - l'ajout --
à une commande qui la prend en charge est une bonne pratique lorsque vous ne pouvez pas contrôler ses arguments, même si ce n'est pas toujours strictement requis ou dangereux.
find . | xargs cmd
est plus efficace (il s'exécute cmd
le moins de fois possible, contrairement à exec
qui s'exécute cmd
une fois pour chaque match). Cependant, vous rencontrerez des problèmes si les noms de fichiers contiennent des espaces ou des caractères géniaux.
Il est suggéré d'utiliser ce qui suit:
find . -print0 | xargs -0 cmd
cela fonctionnera même si les noms de fichiers contiennent des caractères géniaux ( -print0
fait find
imprimer des correspondances terminées par NUL, -0
fait xargs
s'attendre à ce format.)
xargs
approche est en fait beaucoup plus lente s'il n'y a pas (ou seulement quelques) fichiers correspondants et cmd
n'a pas grand-chose à faire pour chaque fichier. Par exemple, lorsqu'elle est exécutée dans un répertoire vide, la xargs
version prendra au moins deux fois le temps, car deux processus doivent être démarrés au lieu d'un seul. (Oui, la différence est généralement imperceptible sur * nix, mais dans une boucle, cela peut être important; ou, essayez-le sous Windows quelque temps ...)