0

I need to append something with particular formatting at the start of a text file. I have looked into How do I append text to the beginning and end of multiple text files in Bash, but not sure how to adapt to my situation.

Code

printf 'Anything\tyou\twant\tto\tadd' 0a . x | ex printf.csv

Expected output

$ head -n 1 printf.csv;
Anything     you    want   to    add

Note: I would prefer a printf solution.

3 Answers 3

4

With ex, that would rather be something like:

printf '%b\n' 0a 'Anything\tyou\twant\tto\tadd' . x | ex -s printf.csv

or:

printf '0a\nAnything\tyou\twant\tto\tadd\n.\nx\n' | ex -s printf.csv

Note that the escape sequences recognised by %b arguments are not the same as that in the format argument. The former are the echo ones, and the latter the standard C-like ones (though many printf implementations have extension over them). That makes not difference for that \t, but it would for \11 which you'd need to write \011 in a %b argument (at least if you wanted to be portable).

Another option, is to use %s but use ksh93-style $'...' quotes for the \t expansion:

printf '%s\n' 0a $'Anything\tyou\twant\tto\tadd' . x | ex -s printf.csv

Where they're supported (ksh93, zsh, bash, FreeBSD sh, busybox ash at least), those $'...' quotes usually support the standard C escapes (with extensions) like in the format argument to printf (unlike %b arguments or echo).

1
  • Cool. I am going to use the last approach. May 22, 2020 at 12:15
3
  1. printf takes a format string as the first non-option argument. If that first argument doesn't make use of the format specifiers like %s, then the rest of the arguments are effectively useless. So, if you want to use the first argument because that's where escape characters like \t are interpreted, the rest of the text must be made to fit in there as well.
  2. As that answer says:

    0a means "Append text after line 0" (in other words, before the first line). The next line is the literal text to "append" after line 0. The period (.) on a line by itself ends the text to be appended.

    0a should come before the text to be appended.

So, something like:

printf '0a\nAnything\tyou\twant\tto\tadd\n.\nx\n' | ex printf.csv 

Example:

% printf '0a\nAnything\tyou\twant\tto\tadd\n.\nx\n' | ex printf.csv
"printf.csv" [New file]
"printf.csv" [New file] 1 line, 25 characters
% cat printf.csv                                                                                 
Anything    you want    to  add
2
  • 2
    Might be more readable: printf "%s\n" 0a $'Anything\tyou\twant\tto\tadd' . x May 22, 2020 at 12:05
  • Thanks all. All answers were good but I'm going to accept this because I understood the explanation better such as the point 1. 👍🏼 May 22, 2020 at 12:14
2

Simply use cat command. It is designed to conCAT files.

Given you have file test.txt with contents:

Test file
Here it is

You can append some text on begining with printf and cat like this: printf "Some fancy text\n" | cat - test.txt.

Some fancy text
Test file
Here it is

You can redirect output to other file and finally save it in the place of old one it that is the case.

printf "Some fancy text\n" | cat - test.txt > /tmp/insertTestFile && mv /tmp/insertTestFile test.txt

This is only a proof of concept. In real life scenario you should consider following limitations:

  • Creating files in /tmp directory with fixed names is bad idea. Consider using tempfile command to create file and store it's name in variable if you need so
  • Using mv across different filesystems causes file to be copied
  • Above solution will create new file and abandon previous one with it's permissions and acl

My intention was to show simple solution that is easy to understand to beginners. Many thanks for all people commenting this answer and pointing out things that may be misleading.

PS. My favourite approach here would be using sed -i '1s/^/Added text\n/' file.txt

6
  • A nice beginner friendly approach! May 22, 2020 at 12:16
  • 2
    @massisenergy, but it's important to warn of the implications there. Creating and writing to tempfiles with fixed name in a world-writable directory like /tmp is very bad practice. That introduces a security vulnerability as an attacker can create a symlink with that name and let you overwrite any file you have write access to. May 22, 2020 at 13:35
  • 1
    Also /tmp is often on its own filesystem. That means that the mv would have to do a copy-and-remove instead of just rename, which means the file will end up being written twice. May 22, 2020 at 13:36
  • 1
    Also note that test.txt will be replaced with a brand new file, so with possibly different metadata like ownership, permissions, ACLs, extended attributes, etc. May 22, 2020 at 13:37
  • 2
    Here the two commands should be chained with && instead of ; as it's important the second one not be run if the first one failed. May 22, 2020 at 13:38

You must log in to answer this question.

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