447 votes

Concaténer plusieurs fichiers mais inclure le nom de fichier comme en-tête de section

Je voudrais concaténer un certain nombre de fichiers texte en un grand fichier dans le terminal. Je sais que je peux le faire en utilisant la commande cat. Cependant, je voudrais que le nom de chaque fichier précède le "vidage de données" de ce fichier. Quelqu'un sait-il comment faire ?

ce que j'ai actuellement :

file1.txt = bluemoongoodbeer

file2.txt = awesomepossum

file3.txt = hownowbrowncow

cat file1.txt file2.txt file3.txt

la sortie souhaitée :

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow

0 votes

J'utilise en fait uuencode & uudecode pour faire quelque chose de similaire, je n'ai pas besoin que le fichier soit lisible entre les deux, j'ai seulement besoin du résultat et de le rediriger vers une autre commande.

3 votes

0 votes

bat est une excellente alternative à cat quand tu veux juste voir le contenu de plusieurs fichiers

675voto

DS. Points 3577

Je cherchais la même chose, et j'ai trouvé cette suggestion :

tail -n +1 file1.txt file2.txt file3.txt

Sortie :

==> file1.txt <==
<contents of file1.txt>

==> file2.txt <==
<contents of file2.txt>

==> file3.txt <==
<contents of file3.txt>

S'il n'y a qu'un seul fichier, l'en-tête ne sera pas imprimé. Si vous utilisez GNU utils, vous pouvez utiliser -v pour toujours imprimer un en-tête.

2 votes

Cela fonctionne également avec GNU tail (qui fait partie de GNU Coreutils).

1 votes

Je veux concaténer un grand nombre de fichiers. Si j'utilise cette méthode ( tail +1 *.txt ) Je reçois une erreur Too many open files . J'ai réparé cela avec : OLD_ULIMIT=`ulimit -n`;ulimit -n 1024;tail +1 *.txt;ulimit -n $OLD_ULIMIT; . Où 1024 était assez grand pour moi.

16 votes

Génial -n +1 option ! Une alternative : head -n-0 file1 file2 file3 .

230voto

Theo Points 421

J'ai utilisé grep pour quelque chose de similaire :

grep "" *.txt

Il ne vous donne pas d'en-tête, mais fait précéder chaque ligne du nom du fichier.

13 votes

La sortie est interrompue si *.txt s'étend à un seul fichier. À cet égard, je conseille grep '' /dev/null *.txt

1 votes

+1 pour m'avoir montré une nouvelle utilisation de grep. cela répondait parfaitement à mes besoins. dans mon cas, chaque fichier ne contenait qu'une ligne, ce qui m'a permis d'obtenir une sortie soigneusement formatée et facilement analysable.

9 votes

grep n'imprimera les en-têtes de fichiers que s'il y a plus d'un fichier. Si vous voulez être sûr de toujours imprimer le chemin du fichier, utilisez -H . Si vous ne voulez pas les en-têtes, utilisez -h . Notez également qu'il imprimera (standard input) pour STDIN.

125voto

Maxim_united Points 89

Cela devrait également faire l'affaire :

find . -type f -print -exec cat {} \;

Moyens :

find    = linux `find` command finds filenames, see `man find` for more info
.       = in current directory
-type f = only files, not directories
-print  = show found file
-exec   = additionally execute another linux command
cat     = linux `cat` command, see `man cat`, displays file contents
{}      = placeholder for the currently found filename
\;      = tell `find` command that it ends now here

Vous pouvez également combiner les recherches à l'aide d'opérateurs booléens tels que -and o -or . find -ls est agréable, aussi.

2 votes

Pourriez-vous expliquer davantage ce que fait cette commande ? C'est exactement ce dont j'ai besoin

0 votes

Et en fait, cela fonctionne bien aussi sans le -print instruction

5 votes

C'est la commande standard find de Linux. Elle recherche tous les fichiers dans le répertoire courant, affiche leur nom, puis pour chacun d'eux, chatte le fichier. En omettant le -print n'imprimera pas le nom du fichier avant la balise cat .

27voto

Chris Points 19350

Cela devrait faire l'affaire :

for filename in file1.txt file2.txt file3.txt; do
    echo "$filename"
    cat "$filename"
done > output.txt

ou pour faire cela pour tous les fichiers texte de manière récursive :

find . -type f -name '*.txt' -print | while read filename; do
    echo "$filename"
    cat "$filename"
done > output.txt

1 votes

N'a pas fonctionné. J'ai juste écrit un code awk très laid : for i in $listoffiles do awk '{print FILENAME,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11}' $i >> concat.txt done

2 votes

...vous pouvez développer ? C'est aussi simple que du code bash.

0 votes

@Nick : votre ligne awk ne devrait même pas fonctionner, étant donné que $0 est la ligne entière, donc vous avez en fait des colonnes répétées là-dedans...

15voto

kevinf Points 401
find . -type f -print0 | xargs -0 -I % sh -c 'echo %; cat %'

Cette méthode permet d'imprimer le nom complet du fichier (y compris le chemin d'accès), puis le contenu du fichier. Elle est également très flexible, puisque vous pouvez utiliser -name "expr" pour la commande find, et exécuter autant de commandes que vous le souhaitez sur les fichiers.

2 votes

Il est également assez simple de le combiner avec les éléments suivants grep . A utiliser avec bash : find . -type f -print | grep PATTERN | xargs -n 1 -I {} -i bash -c 'echo ==== {} ====; cat {}; echo'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X