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?


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

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

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

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

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)

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.


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.