Apprenez en lisant dans l'ordre

xargs — Construire des commandes depuis l'entrée standard

Dispose l'entrée standard en arguments avec echo a b | xargs echo, exécute un mot à la fois avec -n1, place les valeurs dans {} avec -I{}, et traite par lot find . -name '*.log' | xargs — avec schémas et un terminal interactif.

Transformer l'entrée standard en arguments — xargs et -n1

Un pipe passe la sortie de la commande précédente comme entrée standard de la commande suivante. Mais rm et echo ne lisent pas l'entrée standard — ils n'agissent que sur les valeurs écrites comme arguments. xargs est la commande qui prend ce qu'elle reçoit sur l'entrée standard et le réorganise en arguments pour la commande que tu écris après elle, donc avec echo a b | xargs echo, le a et le b deviennent des arguments du echo final.

Par défaut, xargs passe les mots qu'il reçoit à une seule exécution, regroupés autant que possible. Ajoute -n1 et il les sépare, exécutant la commande une fois par mot.

SyntaxeCe que ça fait
| xargsDisposer l'entrée en arguments et exécuter la commande
xargs -n1Exécuter la commande une fois par argument
xargs -I{}Remplacer {} par l'entrée et la placer où tu veux
find ... | xargsLancer un seul traitement par lot sur ce qui a été trouvé
| xargs echo rmAfficher la commande qui s'exécuterait, pour vérifier d'abord
xargs réorganise l'entrée en arguments
echo a b centrée standarda b c| xargs echo| xargs -n1 echoecho a b cregroupé, 1 foisecho a / b / c1 mot, 3 foissortiepasse par pipepasse par pipeexécute 1 foisexécute par mot
La sortie de echo est passée à xargs comme entrée standard et réorganisée en arguments. Une exécution regroupée, ou trois exécutions un mot à la fois — voilà la différence que fait -n1.
printf 'one two three\n' | xargs echo got:        # got: one two three (regroupé, 1 fois)
printf 'one\ntwo\nthree\n' | xargs -n1 echo item:  # item: one / item: two / item: three

① Crée un fichier source de 3 lignes avec printf 'red\ngreen\nblue\n' > colors.txt.

② Passe par pipe la sortie de cat colors.txt dans xargs, en disposant les mots comme arguments de echo pour tous les afficher en une seule exécution regroupée.

③ Passe la même entrée à xargs avec l'option qui la sépare un mot à la fois, et vérifie que echo s'exécute trois fois, une ligne chacune. (Quand tu l'exécutes correctement, une explication apparaît.)

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...

La chaîne de remplacement et l'intégration de find — -I{}

xargs -I{} construit la commande en plaçant chaque ligne d'entrée à la position de `{}`. Comme {} peut aller où tu veux, y compris au milieu de la commande, tu peux exécuter une forme comme echo file_{}.txt — avec du texte fixe autour de la valeur — une ligne à la fois.

Quand tu veux exécuter quelque chose sur les fichiers que find remonte, la forme find ... | xargs est la référence. xargs dispose les chemins que find affiche comme arguments et lance un seul traitement par lot sur les résultats de recherche. Combine-la avec -I{} et tu peux traiter chaque chemin trouvé en les plaçant un à un dans `{}`.

Traiter ce que find remonte avec xargs
find . -name '*.log'a.logb.log| xargs -I{} echo {}place chaque lignedans {}echo a.logecho b.logaffiche les cheminspasse par pipeexécute ligne 1exécute ligne 2
Les chemins que find affiche sont passés à xargs comme une ligne = un élément, et -I{} place chacun dans `{}` et les exécute un à un.
printf 'alpha\nbeta\n' | xargs -I{} echo 'name = {}'   # name = alpha / name = beta
mkdir -p logs                                          # crée le répertoire source
touch logs/a.log logs/b.log                             # crée 2 fichiers
find logs -name '*.log' | xargs -I{} echo 'found {}'    # found logs/a.log / found logs/b.log

① Ajoute l'option de chaîne de remplacement à printf 'cat\ndog\n' | xargs et affiche chaque entrée placée dans le {} de pet = {}.

② Crée un répertoire avec mkdir -p data, puis crée deux fichiers avec touch data/x.txt data/y.txt.

③ Passe par pipe la sortie de find data -name '*.txt' dans xargs et utilise la chaîne de remplacement pour placer chaque chemin dans le {} de echo 'hit {}'.

④ Exécute aussi le simple find data -name '*.txt' | xargs echo et compare-le à la forme où, sans -I{}, les chemins s'alignent à la fin.

Linux console
0 / 5 exécutée(s)
Loading Linux Terminal...

Traiter un à la fois — Choisir entre -n1 et -I{}

-n1 et -I{} exécutent tous deux la commande un élément à la fois, mais ils diffèrent sur l'endroit où va la valeur et la façon dont l'entrée est découpée. -n1 passe les mots (segments séparés par des espaces ou des sauts de ligne) un par un comme arguments finaux de la commande. -I{} prend les lignes une par une et les place à la position où tu as écrit `{}`.

Utilise `-n1` quand tu as juste besoin de la valeur à la fin, et `-I{}` quand tu veux du texte fixe autour de la valeur, comme {}.bak.

Aspect`-n1``-I{}`
Où va la valeurS'aligne à la fin de la commandeVa là où tu as écrit {}
Unité de découpageMots (séparés par espaces/sauts de ligne)Lignes (une ligne = un élément)
Idéal pourPasser simplement les arguments à tour de rôleConstruire une forme avec du texte fixe autour de la valeur
printf 'a\nb\n' | xargs -n1 echo prefix       # prefix a / prefix b (à la fin)
printf 'a\nb\n' | xargs -I{} echo {}_done      # a_done / b_done (placé au milieu)

① Ajoute l'option qui exécute un mot à la fois à printf 'log1\nlog2\n' | xargs, en les passant un par un comme arguments de echo file.

② Passe la même entrée à xargs et utilise l'option de chaîne de remplacement pour les placer dans le {} de echo {}.bak.

③ Compare comment la sortie change entre l'alignement à la fin et le placement au milieu de la commande.

Linux console
0 / 2 exécutée(s)
Loading Linux Terminal...

Le traitement par lot en pratique — Vérifie avant d'exécuter

Dans le travail réel, tu utilises xargs pour des copies et suppressions par lot sur les cibles que find collecte. Comme -I{} peut placer la même valeur à deux endroits ou plus, il fonctionne avec des commandes qui prennent deux arguments comme cp source dest, te permettant de créer d'un coup des sauvegardes « nom d'origine + .bak ».

N'exécute pas tout de suite des opérations irréversibles comme rm. Si tu exécutes xargs echo rm avant xargs rm, la commande qui s'exécuterait est simplement affichée et rien n'est supprimé. Vérifie les cibles listées, puis retire le echo et exécute-la pour de vrai — cette approche en deux temps, vérifier-puis-exécuter, est la façon sûre de procéder.

Vérifier une suppression par lot en l'affichant avant d'exécuter
find . -name '*.tmp'a.tmpb.tmp| xargs echo rm| xargs rmrm a.tmp b.tmpaffiché seulementsupprime les deuxfichiers d'un coupaffiche les cibles① vérifie d'abord② une fois vérifiérien suppriméexécute pour de vrai
Pour les opérations irréversibles, glisse un echo avant rm pour vérifier les cibles en les affichant d'abord, puis exécute.
mkdir -p cache
touch cache/a.tmp cache/b.tmp
find cache -name '*.tmp' | xargs echo rm   # affiche seulement rm cache/a.tmp cache/b.tmp
find cache -name '*.tmp' | xargs rm        # exécute pour de vrai une fois vérifié

① Crée un répertoire de travail avec mkdir -p work, puis crée deux fichiers source avec touch work/note1.txt work/note2.txt.

② Passe par pipe la sortie de find work -name '*.txt' dans xargs et utilise la chaîne de remplacement pour copier chaque fichier vers « le nom d'origine avec .bak ajouté ».

③ Vérifie avec ls work que deux fichiers .bak ont été ajoutés.

④ Passe la sortie de find work -name '*.bak' à xargs, glisse un echo avant la commande de suppression, et vérifie la commande de suppression qui s'exécuterait en l'affichant seulement.

⑤ Si les cibles listées semblent correctes, retire le echo, supprime les fichiers .bak d'un coup, et vérifie de nouveau avec ls work qu'ils ont disparu.

Linux console
0 / 6 exécutée(s)
Loading Linux Terminal...
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Laquelle décrit correctement ce que fait xargs ?

Question 2Comment se comporte printf 'a\nb\nc\n' | xargs -n1 echo ?

Question 3Que représente {} dans xargs -I{} ?