[linux] Concatenating Files And Insert New Line In Between Files

I have multiple files which I want to concat with cat. Let's say

File1.txt 
foo

File2.txt
bar

File3.txt
qux

I want to concat so that the final file looks like:

foo

bar

qux

Instead of this with usual cat File*.txt > finalfile.txt

foo
bar 
qux

What's the right way to do it?

This question is related to linux unix cat

The answer is


In python, this concatenates with blank lines between files (the , suppresses adding an extra trailing blank line):

print '\n'.join(open(f).read() for f in filenames),

Here is the ugly python one-liner that can be called from the shell and prints the output to a file:

python -c "from sys import argv; print '\n'.join(open(f).read() for f in argv[1:])," File*.txt > finalfile.txt

You may do it using xargs if you like, but the main idea is still the same:

find *.txt | xargs -I{} sh -c "cat {}; echo ''" > finalfile.txt

If it were me doing it I'd use sed:

sed -e '$s/$/\n/' -s *.txt > finalfile.txt

In this sed pattern $ has two meanings, firstly it matches the last line number only (as a range of lines to apply a pattern on) and secondly it matches the end of the line in the substitution pattern.

If your version of sed doesn't have -s (process input files separately) you can do it all as a loop though:

for f in *.txt ; do sed -e '$s/$/\n/' $f ; done > finalfile.txt

If you have few enough files that you can list each one, then you can use process substitution in Bash, inserting a newline between each pair of files:

cat File1.txt <(echo) File2.txt <(echo) File3.txt > finalfile.txt

That's how I just did it on OsX 10.10.3

for f in *.txt; do (cat $f; echo '') >> fullData.txt; done

since the simple 'echo' command with no params ended up in no new lines inserted.


This works in Bash:

for f in *.txt; do cat $f; echo; done

In contrast to answers with >> (append), the output of this command can be piped into other programs.

Examples:

  • for f in File*.txt; do cat $f; echo; done > finalfile.txt
  • (for ... done) > finalfile.txt (parens are optional)
  • for ... done | less (piping into less)
  • for ... done | head -n -1 (this strips off the trailing blank line)