J'ai trouvé deux réponses apparemment contradictoires sur StackOverflow aux questions suivantes:
La réponse supérieure à la première question suggère:
find . -name *.txt -print0 | xargs -0 cat >> out.txt
tandis que la réponse supérieure à la deuxième question suggère:
find . -name *.txt -print0 | xargs -0 cat > out.txt
Pour autant que je sache, le premier est correct car il utilise l'opérateur >>
(append), mais pas le second puisqu'il utilise l'opérateur >
que je pensais simplement redirect la sortie vers un file. Cependant, la deuxième réponse a plus de votes (10) et a également été acceptée sans commentaires. Les deux réponses sont-elles correctes? Pourquoi? Quel est le but d'avoir ces deux opérateurs alors?
Le deuxième exemple:
find . -name '*.txt' -print0 | xargs -0 cat > out.txt
Est tout à fait légal et va recréer le file, out.txt
chaque fois qu'il est exécuté, tandis que le premier concatène à out.txt
s'il s'exécute. Mais les deux commands font essentiellement la même chose.
Ce qui prête à confusion est le xargs -0 cat
. Les gens pensent que la redirection vers out.txt
fait partie de cette command quand elle ne l'est pas. La redirection se produit après que xargs -o cat
a entré une input via STDIN, puis en catifiant cette sortie en tant que stream unique vers STDOUT. Le xargs
optimise le chat des files et non leur sortie.
Voici un exemple qui montre ce que je dis. Si nous insérons un pv -l
entre le xargs -0 cat
et la sortie dans le file out.txt
nous pouvons voir le nombre de lignes que cat a écrites.
Pour montrer cela, j'ai créé un directory contenant 10 000 files.
for i in `seq -w 1 10000`;do echo "contents of file$i.txt" > file$i.txt;done
Chaque file ressemble à ceci:
$ more file00001.txt contents of file00001.txt
La sortie de pv
:
$ find . -name '*.txt' -print0 | xargs -0 cat | pv -l > singlefile.rpt 10k 0:00:00 [31.1k/s] [ <=>
Comme nous pouvons le voir, 10k lignes ont été écrites dans mon file singlefile.rpt
. Si xargs
nous passait des morceaux de sortie, alors nous verrions cela par une réduction du nombre de lignes qui étaient présentées à pv
.
Quel est le but d'avoir ces deux opérateurs alors?
C'est facile: parce qu'il y a différents cas d'utilisation. Parfois, il est utile de tronquer le file cible à la taille 0 en premier, parfois (par exemple, les files journaux), il est plus logique d'append des données à un file.
Dans ce cas, cela n'a aucun sens d'append. Vous voulez un file avec exactement le contenu des files que vous avez sélectionnés et non «un file avec toutes datatables au début et le contenu des files sélectionnés à la fin».
J'irais avec le second. La redirection de stdout est interceptée par bash quand vous tapez enter, donc ce n'est pas comme si vous créez une nouvelle redirection pour chaque ligne de find / xargs (ce qui aurait pu être leur reflection). Si out.txt
n'existe pas, il doit être identique, s'il a déjà des données, alors le second réinitialise au less le file au contenu connu (c'est-à-dire, pas de contenu).