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)
linux
unix
command-line
find
dogbane
la source
la source
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:
ou
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.la source
exec
affichera les résultats tels qu'ils sont trouvés, cexargs
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 celaxargs
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.est plus efficace (il s'exécute
cmd
le moins de fois possible, contrairement àexec
qui s'exécutecmd
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:
cela fonctionnera même si les noms de fichiers contiennent des caractères géniaux (
-print0
faitfind
imprimer des correspondances terminées par NUL,-0
faitxargs
s'attendre à ce format.)la source
xargs
approche est en fait beaucoup plus lente s'il n'y a pas (ou seulement quelques) fichiers correspondants etcmd
n'a pas grand-chose à faire pour chaque fichier. Par exemple, lorsqu'elle est exécutée dans un répertoire vide, laxargs
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 ...)Les
xargs
versions modernes prennent souvent en charge l'exécution de pipeline parallèle.Évidemment, cela pourrait être un point pivot lorsqu'il s'agit de choisir entre
find … -exec
et… | xargs
la source