Concatenate multiple files but include filename as section headers

泪湿孤枕 提交于 2019-11-29 18:32:54
DS.

Was looking for the same thing, and found this to suggest:

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

Output:

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

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

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

If there is only a single file then the header will not be printed. If using GNU utils, you can use -v to always print a header.

I used grep for something similar:

grep "" *.txt

It does not give you a 'header', but prefixes every line with the filename.

This should do the trick as well:

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

Means:

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

You further can combine searches trough boolean operators like -and or -or. find -ls is nice, too.

This should do the trick:

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

or to do this for all text files recursively:

find . -type f -name '*.txt' -print | while read filename; do
    echo "$filename"
    cat "$filename"
done > output.txt
find . -type f -print0 | xargs -0 -I % sh -c 'echo %; cat %'

This will print the full filename (including path), then the contents of the file. It is also very flexible, as you can use -name "expr" for the find command, and run as many commands as you like on the files.

Steinfadt

I had a series of files that ended in stats.txt that I wanted to concatenate with the filenames.

I did the following and when there is more than one file, the "more" command includes the filename as a header.

more *stats.txt > stats.txt

or for a general case

more FILES_TO_CONCAT > OUTPUT_FILE

I like this option

for x in $(ls ./*.php); do echo $x; cat $x | grep -i 'menuItem'; done

Output looks like this:

./debug-things.php
./Facebook.Pixel.Code.php
./footer.trusted.seller.items.php
./GoogleAnalytics.php
./JivositeCode.php
./Live-Messenger.php
./mPopex.php
./NOTIFICATIONS-box.php
./reviewPopUp_Frame.php
            $('#top-nav-scroller-pos-<?=$active**MenuItem**;?>').addClass('active');
            gotTo**MenuItem**();
./Reviews-Frames-PopUps.php
./social.media.login.btns.php
./social-side-bar.php
./staticWalletsAlerst.php
./tmp-fix.php
./top-nav-scroller.php
$active**MenuItem** = '0';
        $active**MenuItem** = '1';
        $active**MenuItem** = '2';
        $active**MenuItem** = '3';
./Waiting-Overlay.php
./Yandex.Metrika.php

This is how I normally handle formatting like that:

for i in *; do echo "$i"; echo ; cat "$i"; echo ; done ;

I generally pipe the cat into a grep for specific information.

Gagan

you can use this simple command instead of using a for loop,

ls -ltr | awk '{print $9}' | xargs head

If you like colors, try this:

for i in *; do echo; echo $'\e[33;1m'$i$'\e[0m'; cat $i; done | less -R

or:

tail -n +1 * | grep -e $ -e '==.*'

or: (with package 'multitail' installed)

multitail *

Here is a really simple way. You said you want to cat, which implies you want to view the entire file. But you also need the filename printed.

Try this

head -n99999999 * or head -n99999999 file1.txt file2.txt file3.txt

Hope that helps

And the missing awk solution is:

$ awk '(FNR==1){print ">> " FILENAME " <<"}1' *

This method will print filename and then file contents:

tail -f file1.txt file2.txt

Output:

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

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

If you want to replace those ugly ==> <== with something else

tail -n +1 *.txt | sed -e 's/==>/\n###/g' -e 's/<==/###/g' >> "files.txt"

explanation:

tail -n +1 *.txt - output all files in folder with header

sed -e 's/==>/\n###/g' -e 's/<==/###/g' - replace ==> with new line + ### and <== with just ###

>> "files.txt" - output all to a file

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

If you want the result in the same format as your desired output you can try:

for file in `ls file{1..3}.txt`; \
do echo $file | cut -d '.' -f 1; \ 
cat $file  ; done;

Result:

file1
bluemoongoodbeer
file2
awesomepossum
file3
hownowbrowncow

You can put echo -e before and after the cut so you have the spacing between the lines as well:

$ for file in `ls file{1..3}.txt`; do echo $file | cut -d '.' -f 1; echo -e; cat $file; echo -e  ; done;

Result:

file1

bluemoongoodbeer

file2

awesomepossum

file3

hownowbrowncow
  • AIX 7.1 ksh

... glomming onto those who've already mentioned head works for some of us:

$ r head
head file*.txt
==> file1.txt <==
xxx
111

==> file2.txt <==
yyy
222
nyuk nyuk nyuk

==> file3.txt <==
zzz
$

My need is to read the first line; as noted, if you want more than 10 lines, you'll have to add options (head -9999, etc).

Sorry for posting a derivative comment; I don't have sufficient street cred to comment/add to someone's comment.

For solving this tasks I usually use the following command:

$ cat file{1..3}.txt >> result.txt

It's a very convenient way to concatenate files if the number of files is quite large.

If the files all have the same name or can be matched by find, you can do (e.g.):

find . -name create.sh | xargs tail -n +1

to find, show the path of and cat each file.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!