If you really just want to prepend a line to an existing file, cat
is all you need:
echo 'ColHdr1,ColHdr2,ColHdr3' | cat - file.csv > /tmp/$$ && mv /tmp/$$ file.csv
Or, more efficiently, but perhaps more obscurely, using a group command:
{ echo 'ColHdr1,ColHdr2,ColHdr3'; cat file.csv; } > /tmp/$$ && mv /tmp/$$ file.csv
Note the need to write to a temp. file first, because the shell doesn't support reading from and writing back to the same file using simple output redirection with >
(the output file is truncated before the command executes).
That said, shellter's answer points to a more convenient solution, using sed
's -i
option for (limited) in-place updating (if supported):
OS X and BSD systems (assumes bash
, ksh
, or zsh
):
sed -i '' $'1i\\\nColHdr1,ColHdr2,ColHdr3\n' file.csv
Linux (GNU sed
):
sed -i '1iColHdr1,ColHdr2,ColHdr3' file.csv
-i
for in-place updating is a nonstandard extension to the POSIX standard, and the way it is implemented carries risks, most notably the potential destruction of a symlink. The same applies to the > /tmp/$$ && mv /tmp/$$ ...
approach above.
As for why your approach didn't work:
sed '1s/^/<column names>\n&/' # Fails on OS X: Sed doesn't support \n in the replacement
As an aside: using the g
option for global matching makes no sense, since you're matching the beginning of the line (^
), so there can only be one match by definition.
OS X uses BSD Sed, which doesn't support control-character escape sequences in the replacement part of the s
function call (unlike GNU Sed, which does).
As in the solution above, you could work around the problem with an ANSI C-quoted string ($'...'
) in bash
, ksh
, or zsh
:
sed $'1s/^/<column names>\\\n&/' file.csv
Note the extra \\
, which is needed to \
-escape the literal newline that the \n
expands to by virtue of the ANSI C-quoted string. (Escaping is needed, because a literal newline normally terminates a function call.)
Alternatively use literal newlines in your Sed script - but note that \
-escaping the newline is still needed:
sed '1s/^/<column names>\
&/' file.csv
The above is what the ANSI C-quoted string solution effectively expands to.
If you want to learn about all the differences between the more flexible GNU Sed and BSD Sed, see my answer here.