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.
execaffichera les résultats tels qu'ils sont trouvés, ce xargsqui, 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 xargsne fonctionne pas, la patience est recommandée.
-print0find 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 cmdle moins de fois possible, contrairement à execqui s'exécute cmdune 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 ( -print0fait findimprimer des correspondances terminées par NUL, -0fait xargss'attendre à ce format.)
xargsapproche est en fait beaucoup plus lente s'il n'y a pas (ou seulement quelques) fichiers correspondants et cmdn'a pas grand-chose à faire pour chaque fichier. Par exemple, lorsqu'elle est exécutée dans un répertoire vide, la xargsversion 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 ...)