11

So one can easily join files in bash with cat:

cat *.txt > all.txt

But what if one wants to insert something between the input files, like for example a linefeed?

2 Answers 2

9

Requires GNU sed:

sed -s '$G' *.txt > all.txt

append a line of 8 dashes and a newline after each file

sed -s '$a--------' *.txt

You can use your sed '$d' with that

Compare to these:

Insert a line of dashes before each file:

sed -s '1i--------' *.txt

Do the same, but without a newline after the dashes:

sed -s '1s/^/--------/' *.txt

Put a line of dashes on the end of the last line of each file:

sed -s '$s/$/--------/' *.txt

Surround each file with curly braces:

sed -s -e '1i{' -e '$a}' *.txt
3
  • Elegant solution for inserting linefeed, I made a small modification to only have the linfeeds between the original files not at the end: sed -s '$G' *.txt | sed '$d' > all.txt But can this method also be used to insert other data, to be more in line with the general question? Feb 3, 2010 at 7:16
  • @Roger: sed -s '$a--------' *.txt would append a line of 8 dashes and a newline after each file. You can use your sed '$d' with that. Compare to these: sed -s '1i--------' *.txt, sed -s '1s/^/--------/' *.txt, sed -s '$s/$/--------/' *.txt and sed -s -e '1i{' -e '$a}' *.txt Feb 3, 2010 at 11:09
  • could you add these options to the answer? Feb 4, 2010 at 10:32
8

As a one-liner with subshells:

( for i in *.txt ; do cat $i ; echo 'separator here' ; done ) >all.txt

Here's what the subshell executes split into script-style lines:

for i in *.txt
do
cat $i
echo 'separator goes here' 
done

In this example the separator acts like a footer; add a header by adding another echo before the cat.

5
  • 2
    There is no need for the subshell, and you should use double quotes around the variable expansion to protect any whitespace in the filenames. for i in *.txt; do cat "$i"; echo 'stuff'; done > all.txt Feb 2, 2010 at 1:06
  • Can this be modified to not insert the separator at the end of the result file, only between the original files? Feb 3, 2010 at 7:19
  • @Roger: files=(*.txt); indices=(${!files[@]}); for i in ${indices[@]}; do cat "${files[i]}"; if [[ $i != ${indices[@]: -1} ]]; then echo "separator"; fi; done > all.txt Feb 3, 2010 at 11:19
  • 1
    catWithSep() { sep="$1"; shift; first=''; for f; do test -n "$first" && echo "$sep"; cat "$f"; first=no; done; }; catWithSep separator *.txt Feb 3, 2010 at 11:56
  • @Chris: nice one! Feb 3, 2010 at 19:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .