13

My program writes it state to few files every 30 seconds or so (overwrites) and I would like to look at them with the filenames displayed like "more" does. Like:

$ echo 1234 > test00 $ echo 5678 > test01 $ ls test00 test01 $ more * :::::::::::::: test00 :::::::::::::: 1234 :::::::::::::: test01 :::::::::::::: 5678 

For "more" you have to press space to get next file.

  • What I want is the filenames before content in some way
  • I tried "tail", but have to Ctrl+C, Can write a small program but I’m wondering if any standard unix program can do this ( display name of file, followed by content of file ) without further user interaction as with "more"
1
  • 2
    You had to ctrl-c? Just do tail without -f. It will display the last 10 lines in each file and the filenames. Commented Feb 16, 2015 at 9:30

5 Answers 5

21

If the output from more is acceptable as it is, just pipe it through cat:

more * | cat 

That will do away with the "more" prompts.

Or you can get a bit more control over the display using printf in a one-liner:

for fn in *; do printf "::::::\n$fn\n:::::\n"; cat "$fn"; done 

or as script:

for fn in $*; do printf "vvvvvvvvvv\n$fn\n^^^^^^^^^^\n" cat "$fn" done 
10

You can do a few things.

head and tail are both spec'd to display the first/last ten lines of a file by default - but if called w/ multiple arguments will do that for all and display the filenames for each. And, of course, for each, you can use the -n[num] argument to specify a number of lines other than the default ten that you would like to display. I assume your CTRL-C problem was related to the -f option - which would instruct tail to follow a file - you probably should just leave that out.

Another thing you might do - which will result in output a little different than in the question, but which you might still like, is...

grep -F '' ./*files 

grep is also spec'd to display the filename for its matches when it is given multiple filename arguments - but grep does it at the head of every line. Like

seq 10 >nums.txt; grep -F '' /dev/null nums.txt 

...which prints...

nums.txt:1 nums.txt:2 nums.txt:3 nums.txt:4 nums.txt:5 nums.txt:6 nums.txt:7 nums.txt:8 nums.txt:9 nums.txt:10 

...and highlighted on my terminal. The /dev/null thing is just a little trick to force the multiple file arg behavior even when working with only a single file, and grep -F '' matches every line - even blank ones.

And here's head /dev/null nums.txt:

==> /dev/null <== ==> nums.txt <== 1 2 3 4 5 6 7 8 9 10 

tail's output is identical in this case - but, again, both utilities only print so many lines of a file.

With the latest version of GNU sed you can use the F command like:

sed -s 1F ./*files 

...or if you wanted a little border around the filename...

sed -se '1!b;i\\n---' -e 'F;i\---\n' nums.txt 

...which does like...

--- nums.txt --- 1 2 3 4 5 6 7 8 9 10 

Or if you wanted to get adventurous you could do...

tar -c ./*files | tr -s \\0 | cut -d '' -f1,2,13 | tr '\0' '\n' 

...but that's probably not practical.

4
  • 1
    Gotta love the simplicity of sed -s 1F *files... Commented Feb 16, 2015 at 20:20
  • @don_crissti - it can come in handy - especially in that it takes addresses. You can print the name on any line you choose. But not all linux distributions carry it yet, I guess - this and -z are still considered new of an unstable version by some distros I think. Or, that's what I've been told by others on a few occasions when I've suggested it. I've been using -z for probably a year I think - I dunno when it was released. Commented Feb 16, 2015 at 21:10
  • @don_crissti - there's nothing wrong with any of that - I just get used to doing things a certain way. Also, I find I learn more if I try harder. I use that stuff for fun a lot - and it helps me to learn how to do it myself as well - like what makes things tick. But if I always used -H I wouldn't know what weird stuff I could do with an EOF. So in the answers I like to keep it portable - partly because somebody may not be able to follow along otherwise, but mostly because I wouldn't learn anything writing it otherwise. tar...|sed -z was how I learned to do the impractical thing above. Commented Feb 17, 2015 at 19:10
  • Good suggestion to use head/tail - in addition to being easy to remember it's "safer" too (insofar as it won't flood your terminal if you accidentally try to display a massive file). Commented Apr 16, 2020 at 18:43
4

I would use awk:

awk 'FNR==1{print "::::\n"FILENAME"\n::::"}1' * 
2

The cat replacement bat provides a really nice view of the contents of multiple files, with file names, separators, and line numbers:

$ printf '%s\n' 1234 > test00 $ printf '%s\n' 5 67 8 > test01 $ bat test* ───────┬─────────────────────────────────────── │ File: test00 ───────┼─────────────────────────────────────── 1 │ 1234 ───────┴─────────────────────────────────────── ───────┬─────────────────────────────────────── │ File: test01 ───────┼─────────────────────────────────────── 1 │ 5 2 │ 67 3 │ 8 ───────┴─────────────────────────────────────── 
0

I've used this invocation of tail to do what you are asking. Supplying +1 to --lines (-n) starts with that line number. The -v indicates to always show the filename even if a single filename is processed.

$ echo 1234 > test00 $ echo 5678 > test01 $ ls test00 test01 $ tail -n +1 -v test* ==> test00 <== 1234 ==> test01 <== 5678 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.