6

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?

6

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
  • 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? – Roger Ertesvag Feb 3 '10 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 – Dennis Williamson Feb 3 '10 at 11:09
  • could you add these options to the answer? – Roger Ertesvag Feb 4 '10 at 10:32
6

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.

  • 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 – Chris Johnsen Feb 2 '10 at 1:06
  • Can this be modified to not insert the separator at the end of the result file, only between the original files? – Roger Ertesvag Feb 3 '10 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 – Dennis Williamson Feb 3 '10 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 – Chris Johnsen Feb 3 '10 at 11:56
  • @Chris: nice one! – Dennis Williamson Feb 3 '10 at 19:43

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.