5

I want to prepend a text contained in the file disclaimer.txt to all the .m files in a folder.

I tried the following:

text=$(cat ./disclaimer.txt)

for f in ./*.m
do
   sed -i '1i $text' $f
done

but it just prepends an empty line.

shamalaia
  • 163

2 Answers2

11

There are many ways to do this one, but here's a quick first stab:

#!/bin/sh
for file in *.m; do
    cat disclaimer.txt $file >> $file.$$
    mv $file.$$ $file
done

It concatenates the disclaimer along with the original file into a new temporary file then replaces the original file with the contents of the temporary file.

mjturner
  • 7,300
  • Can you suggest how to add the disclaimer to the second line of each file first line is the title. Also, in the original file if the second line is having some text, I would like to insert a new line there (to make space for the disclaimer)? – Porcupine Jun 24 '18 at 20:19
5

There are two issues with this:

sed -i '1i $text' $f

First, the variable isn't expanded within single quotes, so sed sees the literal string 1i $text.

The second issue is that the i command expects a following backslash, and the line to be added on a second line, so you'd need to do something like this:

$ text="blah"
$ sed -i $'1i\\\n'"$text"$'\n' "$file"

(in shells with the $'...' expansion, or with literal newlines in shells that don't support it.)

Also, the i command can only add one line, the following lines would be taken as additional sed commands.

Though if you have GNU sed, then just sed -i "1i $text" "$f" should work. But you still only get one line.

For multiple lines, it's probably better to something like what @mjturner showed in their answer.

ilkkachu
  • 138,973
  • No, the a and i commands can append/insert multiple lines; e.g., sed $'1i\The quick brown\\\nfox jumps over\\\nthe lazy dog.'.  (Of course you can use literal newlines if you don’t have bash, but that’s hard to represent in a comment.)  In GNU sed, you can do it without newlines in the command: sed -e '1i\' -e 'The quick brown\' -e 'fox jumps over\' -e 'the lazy dog.'.  But this gets messy when the new text is coming from a file (since you need to append a backslash to every line except the last).  … (Cont’d) – G-Man Says 'Reinstate Monica' Aug 23 '20 at 23:01
  • (Cont’d) …  I would suggest sed … 'r disclaimer.txt', but it’s hard to get that at the beginning of the file. (1r acts like 1a; it puts the new text after the first line of the existing file. ex / vi / vim allow 0r to insert the new text before the first line, but sed doesn’t — not even GNU sed.) Ramesh found a workaround, shown here, but doesn’t explain why it’s necessary. – G-Man Says 'Reinstate Monica' Aug 23 '20 at 23:01
  • @G-ManSays'ReinstateMonica', well, something like this, then: sed -i $'1i\\\n'"$(sed -e '$!s/$/\\/' disclaimer)" foo.txt :) – ilkkachu Aug 23 '20 at 23:41