find : -exec vs |xargs

Le
mpg
Bonjour,

Je viens de lire dans un script une utilisation de find dont le résultat est
redirigé vers un xargs. J'avoue être un peu surpris car il me semblait
que -exec était un peu fait pour ça justement.

Quel est donc la différence entre utiliser -exec et xargs : les deux sont-ils
utilisables dans tous les cas ? L'un est-il plus (sûr|souple|performant) dans
certains cas ?

Merci d'avance pour vos avis.

Manuel,
petit scarabée qui découvre find avec émerveillement.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 3
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Luc.Habert.00__arjf
Le #763754
mpg :

Je viens de lire dans un script une utilisation de find dont le résultat est
redirigé vers un xargs. J'avoue être un peu surpris car il me semblait
que -exec était un peu fait pour ça justement.

Quel est donc la différence entre utiliser -exec et xargs : les deux sont-ils
utilisables dans tous les cas ? L'un est-il plus (sûr|souple|performant) dans
certains cas ?


Ça fait grosso-modo le même boulot. Mais le -exec exécute une fois la
commande pour chaque fichier trouvé, tandis que xargs passe un grand nombre
de fichier à la fois (il en case autant qu'il peut avant que ça dépasse la
taille maximale d'une ligne de commande). Donc c'est souvent plus rapide de
passer par xargs.

En revanche, il y a un gros problème : xargs doit redécouper en noms de
fichiers le flux d'octets qu'il reçoit sur son stdin. Avec le find -print
tout bête, qui sépare par des retours à la ligne, ça ne peut pas se faire
fiablement (tu ne peux pas distinguer un nom de fichier contenant un retour
à la ligne de deux noms de fichiers); xargs choisit de découper sur tout le
whitespace, si tu en as dans tes noms de fichiers, boum!

Il y a deux solutions à ça :
- « find -print0 | xargs -0 », là les noms de fichiers sont séparés par des
caractères nuls qui eux ne peuvent vraiment pas apparaitre dans les noms de
fichiers, c'est assez agréable (d'autant que ça permet de nourrir xargs de
manière fiable depuis autre chose que find, ou inversement de nourrir autre
chose qu'xargs), mais ce n'est guère supporté que chez GNU
- « find -exec gnagna '{}' + » (un « + » au lieu du « ; »), qui fait faire
le boulot d'xargs par find, là c'est standard, et ça commence à être
supporté à peu près partout.

Matthieu Moy
Le #763752
(Luc Habert) writes:

Ça fait grosso-modo le même boulot. Mais le -exec exécute une fois la
commande pour chaque fichier trouvé, tandis que xargs passe un grand nombre
de fichier à la fois (il en case autant qu'il peut avant que ça dépasse la
taille maximale d'une ligne de commande). Donc c'est souvent plus rapide de
passer par xargs.


Un « intérêt » de xargs par rapport à -exec, c'est que c'est
utilisable avec autre chose que « find »:

$ n-importe-quelle-commande | une-autre | encore-une-autre | xargs ...

ce qui fait qu'on prend vite l'habitude de passer par xargs. Mais
c'est plutôt une mauvaise habitude si on veut faire quelque chose de
robuste aux espaces dans les noms de fichiers (i.e. dès qu'on veut
faire un script et qu'on est un minimum sérieux ;-) ).

Pour des petits « one-liners » exécutés une seule fois et si on sait
qu'on n'a pas d'espaces dans ses propres noms de fichiers, par contre,
c'est très pratique.

--
Matthieu

F. Senault
Le #763751

Un « intérêt » de xargs par rapport à -exec, c'est que c'est
utilisable avec autre chose que « find »:


Pas de guillemets, hein. Un truc du style :

find [args] > liste
vim liste
cat liste | xargs [args]

C'est pratique pour vérifier que les fichiers trouvés sont bien les
bons, ou quand éditer la liste à la main est plus rapide que de trouver
le bon argument à find / sed / awk / perl pour faire ce qu'on veut.

Fred
--
Did you happen to catch Or did it happen so fast What you thought
would always last Has passed you by Is everything speeding up Or am I
slowing down I'm just spinning around And i don't know why All the
pieces don't fit (Nine Inch Nails, Where Is Everybody)

Stephane Dupille
Le #763750

Hello,

cat liste | xargs [args]


Et quitte à prendre les bonnes habitudes, et apprendre au passage la
signification de UUOC (Useless Use Of Cat) : le « cat » dans la
commande précédente n'est pas nécessaire, il est avantageux de la
remplacer par :

$ xargs [args] < liste



Je reprends mes morceaux de cheveux, et je file...

F. Senault
Le #763749


Hello,

cat liste | xargs [args]


Et quitte à prendre les bonnes habitudes, et apprendre au passage la
signification de UUOC (Useless Use Of Cat)


Blah. Je savais bien que quelqu'un me ferait la réflexion ! :P

Fred
The cat is out of the bag.
--
Just a reflection Just a glimpse Just a little reminder Of all the
what abouts And all the might have Could have beens Another day Some
other way But not another reason to continue And now you're one of us
The wretched (Nine Inch Nails, The Wretched)


Luc.Habert.00__arjf
Le #763499
Matthieu Moy :

Pour des petits « one-liners » exécutés une seule fois et si on sait
qu'on n'a pas d'espaces dans ses propres noms de fichiers, par contre,
c'est très pratique.


Avec un xargs qui supporte le -0, on peut aussi faire des « printf '' »
entre chaque argument, et ça devient robuste. Il m'arrive de pousser la
grotesquerie à faire ça dans des scripts shells, genre dans des wrappers qui
parsent le $@ et le modifient pour le transmettre à un programme, je fais
quelque chose comme :

for arg in "$@" do
if ...; then
...
printf '%s' ...
...
fi
done | xargs -0 commande

. Bon, il y a un petit problème de robustesse si la ligne de commande que
l'on crée dépasse la limite.

Stephane Chazelas
Le #763495
2007-08-31, 09:53(+02), Matthieu Moy:
[...]
ce qui fait qu'on prend vite l'habitude de passer par xargs. Mais
c'est plutôt une mauvaise habitude si on veut faire quelque chose de
robuste aux espaces dans les noms de fichiers (i.e. dès qu'on veut
faire un script et qu'on est un minimum sérieux ;-) ).
[...]


Aux espaces mais aussi aux ', ", et arguments de plus de 256
caracteres (ou octets, je ne me rappelle plus).

--
Stéphane

mpg
Le #763494
Le (on) vendredi 31 août 2007 04:01, Luc Habert a écrit (wrote) :

Quel est donc la différence entre utiliser -exec et xargs : les deux
sont-ils utilisables dans tous les cas ? L'un est-il plus
(sûr|souple|performant) dans certains cas ?


Ça fait grosso-modo le même boulot. Mais le -exec exécute une fois la
commande pour chaque fichier trouvé, tandis que xargs passe un grand
nombre de fichier à la fois (il en case autant qu'il peut avant que ça
dépasse la taille maximale d'une ligne de commande). Donc c'est souvent
plus rapide de passer par xargs.


Oki. D'ailleurs que fait xargs quand il y trop d'arguments ? Il se
débrouille pour faire plusieurs lignes de commande ? Parce que ça doit
quand même arriver assez facilement, en parcourant une grosse arborescence,
non ?

En revanche, il y a un gros problème : xargs doit redécouper en noms de
fichiers le flux d'octets qu'il reçoit sur son stdin. [...] si [...] boum!

Vu.


Il y a deux solutions à ça :
- « find -print0 | xargs -0 », là les noms de fichiers sont séparés par
des caractères nuls qui eux ne peuvent vraiment pas apparaitre dans les
noms de fichiers, c'est assez agréable (d'autant que ça permet de nourrir
xargs de manière fiable depuis autre chose que find, ou inversement de
nourrir autre chose qu'xargs), mais ce n'est guère supporté que chez GNU


Ah. c'est du côté de find, de xargs, ou des deux, que le -0 (resp -print0)
n'est pas trop standard ?

- « find -exec gnagna '{}' + » (un « + » au lieu du « ; »), qui fait faire
le boulot d'xargs par find, là c'est standard, et ça commence à être
supporté à peu près partout.


Oki. C'est sympa ça. et ça gère bien les ligens de commandes un peu
longues ?

Manuel.


Stephane Chazelas
Le #763493
2007-09-01, 21:45(+02), mpg:
Le (on) vendredi 31 août 2007 04:01, Luc Habert a écrit (wrote) :

Quel est donc la différence entre utiliser -exec et xargs : les deux
sont-ils utilisables dans tous les cas ? L'un est-il plus
(sûr|souple|performant) dans certains cas ?


Ça fait grosso-modo le même boulot. Mais le -exec exécute une fois la
commande pour chaque fichier trouvé, tandis que xargs passe un grand
nombre de fichier à la fois (il en case autant qu'il peut avant que ça
dépasse la taille maximale d'une ligne de commande). Donc c'est souvent
plus rapide de passer par xargs.


Oki. D'ailleurs que fait xargs quand il y trop d'arguments ? Il se
débrouille pour faire plusieurs lignes de commande ? Parce que ça doit
quand même arriver assez facilement, en parcourant une grosse arborescence,
non ?


Oui, c'est ce que font xargs et -exec {} +

[...]
Ah. c'est du côté de find, de xargs, ou des deux, que le -0 (resp -print0)
n'est pas trop standard ?


Des deux. En regle generale, les outils Unix sont allergiques au
caractere NUL. Les outils GNU (en general) ne le sont pas.

-print0 et -0 viennent de GNU. Chez GNU, on peut traiter des
"record" NUL-terminated (par opposition a LF-terminated) soit
nativement comme gawk, sort -z, grep -z... soit en passant par
des tr 'n' 'n', avec les outils Unix (tels que specifiés
par la norme), non. Donc, le -0 et -print0 ne font pas exception
et sont non-standard. On ne les trouve que sur les systemes GNU
et certains BSD.


- « find -exec gnagna '{}' + » (un « + » au lieu du « ; »), qui fait faire
le boulot d'xargs par find, là c'est standard, et ça commence à être
supporté à peu près partout.


Oki. C'est sympa ça. et ça gère bien les ligens de commandes un peu
longues ?
[...]


Oui, de la meme facon que xargs.

Attention toutefois, le {} doit preceder le +.

En particulier, on ne peut pas faire:

find ... -exec mv {} /dest +

Avec GNU mv, on peut faire

find ... -exec mv -d /dest {} +

--
Stéphane



Pascal Cabaud
Le #763492

find [args] > liste
vim liste
cat liste | xargs [args]


C'est sans connaitre vip : http://www.cs.duke.edu/~des/vip.html

Publicité
Poster une réponse
Anonyme