Pourquoi ça ne marche pas? «Ls * .txt | xargs cat> all.txt »(tous les fichiers dans un seul document txt)

20

Pourquoi ça ne marche pas?

ls *.txt | xargs cat > all.txt

(Je veux joindre le contenu de tous les fichiers texte dans un seul fichier 'all.txt'.) Find avec -exec devrait également fonctionner, mais j'aimerais vraiment comprendre la syntaxe xargs.

Merci

ajo
la source
1
Mais ne l'utilisez pas lspour cela . Si vous ne pouvez vraiment pas l'utiliser, cat *.txt >all.txtessayez printf '%s\0' *.txt | xargs -r0 cat >allensuite mv all all.txtd'éviter de référencer le fichier lui-même.
tripleee

Réponses:

27

ls *.txt | xargs cat >> all.txt

pourrait fonctionner un peu mieux, car il s'ajouterait à all.txt au lieu de le recréer après chaque fichier.

Soit dit en passant, cat *.txt >all.txtfonctionnerait également. :-)

Janne Pikkarainen
la source
6
Le chat * .txt> all.txt est naturellement meilleur. Merci
ajo
1
Cependant, le ... | xargs cat >> all.txt ou> all.txt renvoie toujours une erreur avec xargs: guillemet simple inégalé ... Est-ce parce que xargs prend tout ce qui suit comme commande?
ajo
1
Avez-vous des noms de fichiers avec des espaces? Si c'est le cas, utilisez plutôt quelque chose comme "find / your / path -iname '* .txt' -print0 | xargs -0 cat >> all.txt" à la place
Janne Pikkarainen
1
non, j'ai remplacé tous les espaces de nom de fichier par . Mais en y réfléchissant, certains noms de fichiers sont susceptibles d'inclure des guillemets simples comme dans listing_O'Connor .txt, cela pourrait être le problème!
ajo
Oui, c'est le problème alors. :) Le moyen le plus simple et le plus sain est d'utiliser find avec -print0 combiné avec xargs -0 - alors toute la chaîne utilisera le caractère NULL comme séparateur et les espaces et les caractères spéciaux seront pris en charge automatiquement.
Janne Pikkarainen
3

Si certains de vos noms de fichiers contiennent ', "ou l'espace xargséchouera à cause du problème du séparateur

En général, ne courez jamais xargssans -0 car il reviendra et vous mordra un jour.

Pensez à utiliser GNU Parallel à la place:

ls *.txt | parallel cat > tmp/all.txt

ou si vous préférez:

ls *.txt | parallel cat >> tmp/all.txt

En savoir plus sur GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
la source
1

all.txt est un fichier dans le même répertoire, donc cat devient confus quand il veut écrire du même fichier dans le même fichier.

D'autre part:

ls *.txt | xargs cat > tmp/all.txt

Cela lira des fichiers texte de votre répertoire actuel dans le all.txt dans un sous-répertoire (non inclus avec *.txt).

Jeremy Smyth
la source
Toujours l'erreur suivante: xargs: guillemet simple inégalé; par défaut, les guillemets sont spéciaux pour xargs, sauf si vous utilisez l'option -0
ajo
1
Avez-vous un fichier .txt avec un guillemet simple dans son nom?
Jeremy Smyth
0

Vous pouvez également rencontrer une limitation de longueur de ligne de commande. Une partie de la raison de son utilisation xargsest qu'il divise l'entrée en blocs sécurisés de la taille d'une ligne de commande. Imaginez donc une situation dans laquelle vous avez des centaines de milliers de fichiers .txt dans le répertoire. ls *.txtéchouera. Vous auriez besoin de faire

ls | grep .txt$ |xargs cat > /some/other/path/all.txt

.txt$dans ce cas est une expression régulière correspondant à tout ce qui se termine par .txt (donc ce n'est pas exactement comme *.txt, car si vous avez un fichier appelé atxt, alors *.txtil ne correspondrait pas, mais l'expression régulière le ferait.)

L'utilisation d'un autre chemin est due au fait que, comme d'autres réponses l'ont souligné, all.txt est mis en correspondance par le modèle, de *.txtsorte qu'il y aurait un conflit entre l'entrée et la sortie.

Notez que si vous avez des fichiers avec 'leur nom (et cela peut être la cause de l' unmatched single quoteerreur), vous voudrez faire

ls | grep --null .txt$ | xargs -0 cat > /some/other/path/all.txt

L'option --null indique à grep d'utiliser une sortie séparée par un caractère \0(aka null) au lieu de la nouvelle ligne par défaut, et l' -0option de `xargs lui dit d'attendre son entrée dans le même format. Cela fonctionnerait même si vous aviez des noms de fichiers avec des retours à la ligne.

Brian Minton
la source