Concaténation de fichiers et insertion d'une nouvelle ligne entre les fichiers

127

J'ai plusieurs fichiers avec lesquels je souhaite concaténer cat. Disons

File1.txt 
foo

File2.txt
bar

File3.txt
qux

Je veux concaténer pour que le fichier final ressemble à:

foo

bar

qux

Au lieu de cela avec d'habitude cat File*.txt > finalfile.txt

foo
bar 
qux

Quelle est la bonne façon de procéder?

Neversaint
la source

Réponses:

121

Tu peux faire:

for f in *.txt; do (cat "${f}"; echo) >> finalfile.txt; done

Assurez-vous que le fichier finalfile.txtn'existe pas avant d'exécuter la commande ci-dessus.

Si vous êtes autorisé à utiliser, awkvous pouvez faire:

awk 'FNR==1{print ""}1' *.txt > finalfile.txt
codaddict
la source
10
AWK '{print $0}' *.txt
timger
7
Cela a le défaut distinct qu'il y aura des lignes vides soit à la fin (à partir de la première alternative) soit au début (deuxième alternative). awk 'FNR==1 && NR > 1 ...'Cependant, vous pouvez facilement vous prémunir contre cela .
tripleee
5
Si vous mettez >finalfile.txtaprès le, donevous pouvez écraser au lieu d'ajouter, ce qui supprimera l'exigence de s'assurer que le fichier est manquant ou vide avant la boucle.
tripleee
53

Si vous avez suffisamment de fichiers pour pouvoir les lister, vous pouvez utiliser la substitution de processus dans Bash, en insérant une nouvelle ligne entre chaque paire de fichiers:

cat File1.txt <(echo) File2.txt <(echo) File3.txt > finalfile.txt
Robert Tupelo-Schneck
la source
1
Belle! Merci.
Bob Kocisko
Cela a bien fonctionné pour moi pour mes certificats Letsencrypt pour créer des fichiers .pem.
leeman24
35

Si c'était moi, j'utiliserais sed:

sed -e '$s/$/\n/' -s *.txt > finalfile.txt

Dans ce modèle sed, $ a deux significations, premièrement, il correspond au dernier numéro de ligne uniquement (comme une plage de lignes sur laquelle appliquer un modèle) et deuxièmement, il correspond à la fin de la ligne dans le modèle de substitution.

Si votre version de sed n'a pas -s(traiter les fichiers d'entrée séparément), vous pouvez tout faire en boucle:

for f in *.txt ; do sed -e '$s/$/\n/' $f ; done > finalfile.txt
Flexo
la source
3
Ou dans GNU sed:sed -s '$G' *.txt > finalfile.txt
Ruud Helderman
Un seul flux! cela devrait être la réponse acceptée!
Yassine ElBadaoui
attention les gars, je viens de planter mon PC parce que je l'ai utilisé findà la place du *.txt, ce qui signifiait que le fichier était ajouté sur lui-même!
Xerus
11

Vous pouvez le faire en utilisant xargssi vous le souhaitez, mais l'idée principale est toujours la même:

find *.txt | xargs -I{} sh -c "cat {}; echo ''" > finalfile.txt
Nick Roz
la source
1
Merci. Je trouve xargsbeaucoup plus facile à utiliser que les boucles en bash.
RawwrBag
9

Cela fonctionne dans Bash:

for f in *.txt; do cat $f; echo; done

Contrairement aux réponses avec >>(append), la sortie de cette commande peut être redirigée vers d'autres programmes.

Exemples:

  • for f in File*.txt; do cat $f; echo; done > finalfile.txt
  • (for ... done) > finalfile.txt (les parents sont facultatifs)
  • for ... done | less (piping en moins)
  • for ... done | head -n -1 (cela supprime la ligne vierge de fin)
user3780389
la source
7

C'est comme ça que je viens de le faire sur OsX 10.10.3

for f in *.txt; do (cat $f; echo '') >> fullData.txt; done

puisque la simple commande 'echo' sans paramètre n'a abouti à aucune nouvelle ligne insérée.

lbrutti
la source
Cela place la chaîne à la fin du fichier; comment puis-je l'insérer entre chaque fichier?
onassar
3

En python, cela concatène avec des lignes vides entre les fichiers (le ,supprime l'ajout d'une ligne vierge de fin supplémentaire):

print '\n'.join(open(f).read() for f in filenames),

Voici le vilain python one-liner qui peut être appelé à partir du shell et imprime la sortie dans un fichier:

python -c "from sys import argv; print '\n'.join(open(f).read() for f in argv[1:])," File*.txt > finalfile.txt
user3780389
la source