0

I am looking for a bash one-liner which can cat a number of files with a number of fixed lines.

file1.txt:

file1 line 1
file1 line 2

file2.txt

file2 line 1
file2 line 2

Then I am looking for something like

cat-with-strings foo file1.txt bar file2.txt baz

producing output

foo
file1 line 1
file1 line 2
bar
file2 line 1
file2 line 2
baz

How can I do this in a single line of bash, using standard linux tools (sed, awk, cat, etc) and without creating any files to hold foo, bar, or baz?

5 Answers 5

2
sh -c 'while [ $# -gt 0 ] ; do echo "$1" ; cat "${2:-/dev/null}" ; shift 2 2>/dev/null; done' - foo file1 bar file2 baz

In general requiring this to be a 1-liner is pretty silly, who cares if it is one line if you put it in a shell function or file?

2

With one command using any awk in any shell on every Unix box

$ awk 'FNR==1{print x} 1; END{print x}' x='foo' file1 x='bar' file2 x='baz'
foo
file1 line 1
file1 line 2
bar
file2 line 1
file2 line 2
baz
1
  • 1
    Note that it assumes non-empty files. Commented Jul 7 at 6:59
1

Typing on my phone so apologies for a sketch, untested answer.

Surely you can just concatinate (cat) everything as if everything was a file:

cat <( echo foo ) file1.txt <( echo bar ) file2.txt <( echo baz )
1

With perl and any shell:

perl -pe1 'echo foo|' file1 'echo bar|' file2 'echo baz|'

With zsh, see also (only for mmap()able files such as regular files):

zmodload zsh/mapfile
print -rl foo $mapfile[file1] bar $mapfile[file2] baz
1

Why does it have to be a single cat command? What's wrong with simply:

echo foo ; cat file1 ; echo bar ; cat file2 ; echo baz

Or for that matter, why cat?


Let's unwind that, since it's easier for humans to read, and works just the same.

 echo foo
 cat file1
 echo bar
 cat file2
 echo baz

If you need "a single string", multi-line strings are fine too:

sh -c "
 echo foo
 cat file1
 echo bar
 cat file2
 echo baz
"

If you had in mind to redirect the output, that's easy:

{
 echo foo
 cat file1
 echo bar
 cat file2
 echo baz
} > output.file

If you wanted it in a pipeline, that's easy too, as commands within a pipeline are not restricted to “simple” commands:

{
 echo foo
 cat file1
 echo bar
 cat file2
 echo baz
} |
other_cmd

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.