Comment ajouter le contenu de plusieurs fichiers dans un seul fichier

174

Je souhaite copier le contenu de cinq fichiers dans un seul fichier tel quel. J'ai essayé de le faire en utilisant cp pour chaque fichier. Mais cela écrase le contenu copié à partir du fichier précédent. J'ai aussi essayé

paste -d "\n" 1.txt 0.txt

et cela n'a pas fonctionné.

Je veux que mon script ajoute la nouvelle ligne à la fin de chaque fichier texte.

par exemple. Fichiers 1.txt, 2.txt, 3.txt. Mettre le contenu de 1,2,3 dans 0.txt

Comment fait-on ça ?

Vapeur
la source
1
duplication possible des fichiers
Nikos C.
Une autre réponse ici: stackoverflow.com/questions/2576693/…
Nikos C.

Réponses:

308

Vous avez besoin de la commande cat(abréviation de concatenate), avec la redirection shell ( >) dans votre fichier de sortie

cat 1.txt 2.txt 3.txt > 0.txt
radical7
la source
8
devrait être >> non? et aussi pourquoi y a-t-il une nouvelle ligne avant tout le texte de mon fichier 0.txt?
Steam
1
vouliez-vous conserver le contenu de 0.txt?
sehe
13
@blasto ça dépend. Vous utiliseriez >>pour ajouter un fichier à un autre, où > écrase le fichier de sortie avec tout ce qui y est dirigé. Quant à la nouvelle ligne, y a-t-il une nouvelle ligne comme premier caractère dans le fichier 1.txt? Vous pouvez le découvrir en utilisant od -cet voir si le premier caractère est un \n.
radical7
1
@ radical7 Merci. En fait, mes fichiers sont comme foo_1, foo_2, foo_3. J'ai essayé de modifier votre code comme - cat "$ filename _" {1,2,3} ". Txt", mais cela n'a pas fonctionné.
Steam
1
@blasto Vous allez certainement dans la bonne direction. Bash accepte certainement le formulaire {...}de correspondance de nom de fichier, alors peut-être que les citations ont un peu gâché les choses dans votre script? J'essaie toujours de travailler avec des choses comme celle-ci en utilisant lsdans un shell. Lorsque j'obtiens la bonne commande, je la coupe-n-collez simplement dans un script tel quel. Vous pouvez également trouver l' -xoption utile dans vos scripts - elle fera écho aux commandes développées dans le script avant l'exécution.
radical 7
97

Une autre option, pour ceux d'entre vous qui tombent encore sur ce post comme je l'ai fait, est d'utiliser find -exec:

find . -type f -name '*.txt' -exec cat {} + >> output.file

Dans mon cas, j'avais besoin d'une option plus robuste qui examinerait plusieurs sous-répertoires, j'ai donc choisi de l'utiliser find. Décomposer:

find .

Regardez dans le répertoire de travail actuel.

-type f

Intéressé uniquement par les fichiers, pas par les répertoires, etc.

-name '*.txt'

Réduire le jeu de résultats par nom

-exec cat {} +

Exécutez la commande cat pour chaque résultat. "+" signifie qu'une seule instance de catest générée (merci @gniourf_gniourf)

 >> output.file

Comme expliqué dans d'autres réponses, ajoutez le contenu cat-ed à la fin d'un fichier de sortie.

mopo922
la source
10
Il y a beaucoup de défauts dans cette réponse. Tout d'abord, le caractère générique *.txtdoit être entre guillemets (sinon, la findcommande entière , telle qu'elle est écrite, est inutile). Une autre faille vient d'une idée fausse: la commande qui est exécutée n'est pas cat >> 0.txt {} , mais cat {}. Votre commande est en fait équivalente à { find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(j'ai ajouté le regroupement pour que vous vous rendiez compte de ce qui se passe réellement). Un autre défaut est qu'il findva trouver le fichier 0.txtet catse plaindra en disant que le fichier d'entrée est le fichier de sortie .
gniourf_gniourf
Merci pour les corrections. Mon cas était un peu différent et je n'avais pas pensé à certains de ces pièges appliqués à ce cas.
mopo922
Vous devriez mettre >> output.fileà la fin de votre commande, afin de ne pas induire personne (y compris vous-même) à penser que findcela s'exécutera cat {} >> output.filepour chaque fichier trouvé.
gniourf_gniourf
Commence à avoir l'air vraiment bien! Une dernière suggestion: utiliser à la -exec cat {} +place de -exec cat {} \;, de sorte qu'une seule instance de catsoit générée avec plusieurs arguments ( +est spécifié par POSIX ).
gniourf_gniourf
3
Bonne réponse et mot d'avertissement - j'ai modifié le mien en: find . -type f -exec cat {} + >> outputfile.txtet je ne pouvais pas comprendre pourquoi mon fichier de sortie n'arrêterait pas de se développer dans les concerts même si le répertoire ne faisait que 50 Mo. C'était parce que je continuais à ajouter outputfile.txt à lui-même! Assurez-vous donc de nommer ce fichier correctement ou de le placer entièrement dans un autre répertoire pour éviter cela.
Thisisstackoverflow
43

si vous avez un certain type de sortie, faites quelque chose comme ça

cat /path/to/files/*.txt >> finalout.txt
Eswar Yaganti
la source
1
Gardez à l'esprit que vous perdez la possibilité de maintenir l'ordre de fusion. Cela peut vous affecter si vos fichiers sont nommés, par exemple. file_1,, file_2file_11, En raison de l'ordre naturel de tri des fichiers.
emix
16

Si tous vos fichiers sont dans un seul répertoire, vous pouvez simplement faire

cat * > 0.txt

Les fichiers 1.txt, 2.txt, .. iront dans 0.txt

Pooja
la source
Déjà répondu par Eswar. Gardez à l'esprit que vous perdez la possibilité de maintenir l'ordre de fusion. Cela peut vous affecter si vos fichiers sont nommés, par exemple. file_1,, file_2file_11, En raison de l'ordre naturel de tri des fichiers.
emix
10
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

J'ai trouvé cette page parce que j'avais besoin de joindre 952 fichiers en un seul. J'ai trouvé que cela fonctionnait beaucoup mieux si vous avez de nombreux fichiers. Cela fera une boucle pour le nombre de nombres dont vous avez besoin et chattera chacun en utilisant >> pour ajouter à la fin de 0.txt.

freddythunder
la source
vous pouvez utiliser l'expansion d'accolades dans bash pour écrire cat {1,2,3} .txt >> 0.txt
mcheema
9

Si tous vos fichiers sont nommés de la même manière, vous pouvez simplement faire:

cat *.log >> output.log
AeaRy
la source
5

Une autre option est sed:

sed r 1.txt 2.txt 3.txt > merge.txt 

Ou...

sed h 1.txt 2.txt 3.txt > merge.txt 

Ou...

sed -n p 1.txt 2.txt 3.txt > merge.txt # -n is mandatory here

Ou sans redirection ...

sed wmerge.txt 1.txt 2.txt 3.txt

Notez que la dernière ligne écrit aussi merge.txt(pas wmerge.txt!). Vous pouvez utiliser w"merge.txt"pour éviter toute confusion avec le nom du fichier, et-n pour une sortie silencieuse.

Bien sûr, vous pouvez également raccourcir la liste des fichiers avec des caractères génériques. Par exemple, dans le cas de fichiers numérotés comme dans les exemples ci-dessus, vous pouvez spécifier la plage entre accolades de cette manière:

sed -n w"merge.txt" {1..3}.txt
Fran
la source
4

si vos fichiers contiennent des en- têtes et que vous souhaitez les supprimer dans le fichier de sortie, vous pouvez utiliser:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done
Brunocrt
la source
3

Si le fichier d'origine contient des caractères non imprimables, ils seront perdus lors de l'utilisation de la commande cat. En utilisant 'cat -v', les non-imprimables seront convertis en chaînes de caractères visibles, mais le fichier de sortie ne contiendrait toujours pas les caractères non imprimables réels dans le fichier d'origine. Avec un petit nombre de fichiers, une alternative pourrait être d'ouvrir le premier fichier dans un éditeur (par exemple vim) qui gère les caractères non imprimables. Ensuite, déplacez-vous vers le bas du fichier et entrez ": r second_file_name". Cela attirera le deuxième fichier, y compris les caractères non imprimables. La même chose pourrait être faite pour les fichiers supplémentaires. Lorsque tous les fichiers ont été lus, entrez ": w". Le résultat final est que le premier fichier contiendra désormais ce qu'il faisait à l'origine, plus le contenu des fichiers qui ont été lus.

BACooper
la source
Ce n'est pas très scriptable.
FKEinternet
1

Si vous souhaitez ajouter le contenu de 3 fichiers dans un seul fichier, la commande suivante sera un bon choix:

cat file1 file2 file3 | tee -a file4 > /dev/null

Il combinera le contenu de tous les fichiers dans file4, jetant la sortie de la console vers /dev/null.

Ajit K'sagar
la source