Concaténation de plusieurs fichiers texte en un seul fichier dans Bash

305

Quelle est la manière la plus rapide et la plus pragmatique de combiner tous les fichiers * .txt d'un répertoire en un seul grand fichier texte?

Actuellement, j'utilise Windows avec cygwin, j'ai donc accès à BASH.

La commande shell Windows serait bien aussi mais je doute qu'il y en ait une.

Yada
la source

Réponses:

537

Cela ajoute la sortie à all.txt

cat *.txt >> all.txt

Cela écrase all.txt

cat *.txt > all.txt
Robert Greiner
la source
30
vous pouvez rencontrer un problème où il fait all.txt dans all.txt ... J'ai parfois ce problème avec grep, je ne sais pas si cat a le même comportement.
rmeador
8
@rmeador oui, c'est vrai, si all.txt existe déjà, vous aurez ce problème. Ce problème est résolu en fournissant au fichier de sortie une extension différente ou en déplaçant all.txt dans un dossier différent.
Robert Greiner
2
cat * .txt >> tmp; mv tmp all.txt (et assurez-vous que all.txt n'existe pas au préalable)
Renaud
16
J'obtiens une "Liste d'arguments trop longue" - je suppose qu'elle ne peut pas gérer plus de 40 000 fichiers.
Matt
32
Évitez la liste d'arguments trop longue avec:echo *.txt | xargs cat > all.txt
5heikki
145

N'oubliez pas, pour toutes les solutions données jusqu'à présent, le shell décide de l'ordre dans lequel les fichiers sont concaténés. Pour Bash, IIRC, c'est l'ordre alphabétique. Si l'ordre est important, vous devez soit nommer les fichiers de manière appropriée (01file.txt, 02file.txt, etc ...) ou spécifier chaque fichier dans l'ordre dans lequel vous voulez qu'il soit concaténé.

$ cat file1 file2 file3 file4 file5 file6 > out.txt
Chinmay Kanchi
la source
33

La commande shell Windows typepeut faire ceci:

type *.txt >outputfile

La typecommande Type écrit également les noms de fichiers dans stderr, qui ne sont pas capturés par l' >opérateur de redirection (mais s'afficheront sur la console).

Greg Hewgill
la source
2
Sachez simplement que si vous placez le fichier de sortie dans le même répertoire que le fichier d'origine, cela entraînera une duplication car il combinera également le nouveau fichier de sortie deux fois.
CathalMF
26

Vous pouvez utiliser le shell Windows copypour concaténer des fichiers.

C:\> copy *.txt outputfile

De l'aide:

Pour ajouter des fichiers, spécifiez un seul fichier pour la destination, mais plusieurs fichiers pour la source (en utilisant des caractères génériques ou le format file1 + file2 + file3).

Carl Norum
la source
Ceci, en tant que solution la plus propre à
mon humble avis,
OP a demandé Bash.
Big Rich
2
Avez-vous lu la question? "La commande shell Windows serait bien aussi ..."
Carl Norum
8

Soyez prudent, car aucune de ces méthodes ne fonctionne avec un grand nombre de fichiers. Personnellement, j'ai utilisé cette ligne:

for i in $(ls | grep ".txt");do cat $i >> output.txt;done

EDIT: Comme quelqu'un l'a dit dans les commentaires, vous pouvez remplacer $(ls | grep ".txt")par$(ls *.txt)

EDIT: grâce à l'expertise de @gnourf_gnourf, l'utilisation de glob est la bonne façon d'itérer sur les fichiers d'un répertoire. Par conséquent, les expressions blasphématoires comme $(ls | grep ".txt")doivent être remplacées par *.txt(voir l'article ici ).

Bonne solution

for i in *.txt;do cat $i >> output.txt;done
Jacobe2169
la source
1
Pourquoi ne pas for i in $(ls *.txt);do cat $i >> output.txt;done?
streamofstars
2
Lien ParsingLs obligatoire , avec un downvote (et vous méritez plus d'un downvote, car ls | grepc'est un très mauvais contre-modèle).
gniourf_gniourf
J'ai obtenu un vote positif de ma part car cela permet des tests / opérations arbitraires par nom de fichier avant la sortie et c'est rapide et facile et bon pour la pratique. (Dans mon cas, je voulais: pour i in *; do echo -e "\ n $ i: \ n"; cat $ 1; done)
Nathan Chappell
L' ls *.txtéchec ne serait-il pas trop important (liste d'arguments trop longue)?
Rafael Almeida
6

la manière la plus pragmatique avec le shell est la commande cat. d'autres moyens incluent,

awk '1' *.txt > all.txt
perl -ne 'print;' *.txt > all.txt
ghostdog74
la source
1
Cela devrait être la bonne réponse dans la plupart des cas. Si un fichier texte ne contient pas de nouvelle ligne vide, l'utilisation de toutes les catméthodes ci-dessus concaténera la dernière ligne et la première ligne des fichiers adjacents.
mootmoot
6

Et cette approche?

find . -type f -name '*.txt' -exec cat {} + >> output.txt
GPrathap
la source
Étant donné que OP indique que les fichiers se trouvent dans le même répertoire, vous devrez peut-être ajouter -maxdepth 1à la findcommande.
codeforester
1
Fonctionne très bien avec un grand nombre de fichiers, où l'approche de la réponse acceptée échoue
amine
ah j'aimerais savoir ce que cela signifie plus et double redirection ...
hello_earth
Ce devrait être la bonne réponse. Cela fonctionnera correctement dans un script shell. Voici une méthode similaire si vous souhaitez trier la sortie:sort -u --output="$OUTPUT_FILE" --files0-from=- < <(find "$DIRECTORY_NAME" -maxdepth 1 -type f -name '*.txt' -print0)
steveH
3
type [source folder]\*.[File extension] > [destination folder]\[file name].[File extension]

Par exemple:

type C:\*.txt > C:\1\all.txt

Cela prendra tous les fichiers txt dans le dossier C: \ et l'enregistrera dans le dossier C: \ 1 sous le nom de all.txt

Ou

type [source folder]\* > [destination folder]\[file name].[File extension]

Par exemple:

type C:\* > C:\1\all.txt

Cela prendra tous les fichiers présents dans le dossier et y placera le contenu dans C: \ 1 \ all.txt

Ou Je
la source
0

Vous pouvez faire comme ça: cat [directory_path]/**/*.[h,m] > test.txt

si vous utilisez {}pour inclure l'extension des fichiers que vous recherchez, il y a un problème de séquencement.

Michael-zhang
la source
0

Lorsque vous rencontrez un problème où il cat all.txt dans all.txt, vous pouvez essayer de vérifier que all.txt est existant ou non, s'il existe, supprimer

Comme ça:

[ -e $"all.txt" ] && rm $"all.txt"

Leo
la source
cat *.txt > all.txt >commande écrase all.txt s'il existe >>ajoute des données au fichier existant
Oleg Bondarenko
-4

tout cela est méchant ...

ls | grep *.txt | while read file; do cat $file >> ./output.txt; done;

trucs faciles.

kSiR
la source
6
Eeek! Ne fais pas ça. Fairefind . -iname "*.txt" -maxdepth 1 -exec cat {} >> out.txt \;
Chinmay Kanchi