25

Is there a command to show the directory or file name when using cat to display the contents of files?

For example: assume two files f1.txt and f2.txt are in ./tmp

./tmp/f1.txt
./tmp/f2.txt 

Then when I do cat ./tmp/*.txt, only the content of the files will be shown. But how to first show the file name, then the content? e.g.:

 (The needed command):
 ./tmp/f1.txt:  
 This is from f1.txt
 and so on
 ./tmp/f2.txt:
 This is from f2.txt ...

Is there a command to do it? (There seems to be no option for cat to show the file names.)

1

9 Answers 9

38

Just as another idea, try tail -n +1 ./tmp/*.txt

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

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

==> ./tmp/file3.txt <==
<contents of file3.txt>
2
  • 2
    This is nice, but how to display the filename if there is only one file?
    – mvorisek
    Commented Jan 19, 2021 at 20:14
  • 4
    @mvorisek, with the GNU implementation of tail at least, you'd use the -v option for that. Commented Jun 14, 2021 at 14:48
11
$ for file in ./tmp/*.txt; do printf '%s\n' "$file";  cat "$file"; done

-or-

$ find ./tmp -maxdepth 1 -name "*.txt" -print -exec cat "{}" \;
0
6

Not exactly what you asked for, but you can prefix each line with the filename:

$ grep '^' ./tmp/*.txt
./tmp/f1.txt: this is from f1.txt
./tmp/f1.txt: blaa, blaa, blaa...
./tmp/f1.txt: blaa, blaa, blaa...
./tmp/f2.txt: this is from f2.txt
./tmp/f2.txt: blaa, blaa, blaa...
./tmp/f2.txt: blaa, blaa, blaa...

It will be tough to do much better than this without resorting to a little scripting.

2
  • 2
    That is a good workaround - my files are actually single line.
    – lukmac
    Commented Aug 28, 2012 at 16:19
  • This would not output any filenames if the glob matches only a single file.
    – Kusalananda
    Commented May 3, 2023 at 15:14
4

Not enough reputation point to add a comment to second answer

tail -v -n +1 /tmp/*.txt

will display filename even if there is only one file.

3

You could easily write a tiny script doing just that,

for f; 
do 
  echo "This is from $f";
  cat -- "$f";
done
7
  • Thanks, but is there a way to avoid using script - by using a command?
    – lukmac
    Commented Aug 28, 2012 at 15:49
  • To my knowledge, there is not such a command
    – juampa
    Commented Aug 28, 2012 at 15:52
  • 2
    What is the practical difference between a script and a command, or, why does it matter that multiple commands are entered on a single command-line to solve the problem? The command doesn't have to be in a file. You can run the "script" by just typing in the text given.
    – kbulgrien
    Commented Aug 28, 2012 at 15:59
  • That is true - but i want to use something existed, please see the answer from "ire_and_curses" and "kbulgrien"
    – lukmac
    Commented Aug 28, 2012 at 16:14
  • 3
    Please use "$@" instead of $*, as the former will handle filenames with spaces (this is part of POSIX shell, it's not a bash-ism). Also, cat "$f".
    – derobert
    Commented Aug 28, 2012 at 16:37
2
grep . *.txt 

Matches all lines and also shows file names

2
  • 2
    . doesn't match empty lines
    – Evgeny
    Commented Aug 6, 2015 at 17:13
  • 1
    Only shows filenames if there are more than a single file.
    – Kusalananda
    Commented May 3, 2023 at 15:13
1
find . -name '*' -execdir cat '{}' \;

When a directory is passed to cat, you'll see something like:

cat: ./chapter_01: Is a directory

Immediately following, the find will cat the contents of that directory.

1

More gives nice headings, poor cat though:

$ more *.txt | cat
::::::::::::::
file1.txt
::::::::::::::
line1
line2

::::::::::::::
file2.txt
::::::::::::::
line1
line2
line3

...and so on.

0

cat is (intentionally) an extremely simple command that just reads one file stream and dumps it to another (with a few basic formatting options). It'd be fairly easy to create a utility based on cat that did provide the filename, but standard versions won't do this -- probably because it's easy to replicate with other commands.

If you want to examine the pages manually you could use 'less'. This will give you the filename at the end of every file, in the format: 'foo.txt (file 1 of 100) (END) - Next: bar.txt).

You must log in to answer this question.