4

I want to write a bash script that takes my file:

READ_ME.MD

two
three
four

and makes it

READ_ME.MD

one
two
three
four

There are a bunch of similar StackOverflow questions, but I tried their answers and haven't been successful.

These are the bash scripts that I have tried and failed with:


test.sh

sed '1s/^/one/' READ_ME.md > READ_ME.md

Result: Clears the contents of my file


test.sh

sed '1,1s/^/insert this /' READ_ME.md > READ_ME.md

Result: Clears the contents of my file


test.sh

sed -i '1s/^/one\n/' READ_ME.md

Result: sed: 1: "READ_ME.md": invalid command code R


Any help would be appreciated.

c_idle
  • 1,448
  • 4
  • 22
  • 40
  • You could write to `READ_ME.md.tmp`, and then `mv READ_ME.md.tmp READ_ME.md`. Or use `cat READ_ME.md | sed ... > READ_ME.md`. The problem is you're truncating the file before it's read. – Robert Seaman Apr 11 '18 at 15:15
  • Use >> to append to the file. > will overwrite it. – BSUK Apr 11 '18 at 15:37

4 Answers4

2

You can use this BSD sed command:

sed -i '' '1i\
one
' file

-i will save changes inline to file.


If you want to add a line at the top if same line is not already there then use BSD sed command:

line='one'

sed -i '' '1{/'"$line"'/!i\
'"$line"'
}' file
anubhava
  • 761,203
  • 64
  • 569
  • 643
2

Your last example works for me with GNU sed. Based on the error message you added, I'd guess you're working on a Mac system? According to this blog post, a suffix argument may be required on Mac versions of sed:

sed -i ' ' '1s/^one\n/' READ_ME.md
John Moon
  • 924
  • 6
  • 10
  • 2
    `-i""` is **exactly** the same as `-i` -- there's no possible way `sed` can distinguish them, since they generate the same array of C strings after being parsed, and the actual OS-level interface whereby programs are invoked is the `execve` syscall, which accepts only such an array (and doesn't receive or otherwise have access to the original command line in full). Thus, it *absolutely must* be `-i ''`, with a space, to pass an empty string. – Charles Duffy Apr 11 '18 at 15:47
  • Good point, I hadn't considered that. Edited. Thanks, Charles! – John Moon Apr 11 '18 at 16:18
  • `-i ' '` -> with a space – kyodev Apr 11 '18 at 19:31
1

If this is bash or zsh, you can use process substitution like so.

% cat x
one
two 
three

% cat <(echo "zero") x
zero
one
two 
three

Redirect this into a temp file and copy it back to the original

Noufal Ibrahim
  • 71,383
  • 13
  • 135
  • 169
0

there is always ed

printf '%s\n' H 1i "one" . w | ed -s READ_ME.MD
karakfa
  • 66,216
  • 7
  • 41
  • 56