As far as I know there is no prepend operator on a bash or any other shell, however there are many ways to do the same. You can use ed, sed, perl, awk and so on to add text to the beginning of a file in Bash under Linux or Unix-like systems.
1s;^;to be prepended; substitutes the beginning of the first line by the given replacement string, using ; as a command delimiter.
Using '>>' with 'echo' command appends a line to a file. Another way is to use 'echo,' pipe(|), and 'tee' commands to add content to a file.
Append Text Using >> Operator The >> operator redirects output to a file, if the file doesn't exist, it is created but if it exists, the output will be appended at the end of the file. For example, you can use the echo command to append the text to the end of the file as shown.
This still uses a temp file, but at least it is on one line:
echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile
Credit: BASH: Prepend A Text / Lines To a File
echo '0a
your text here
.
w' | ed some_file
ed is the Standard Editor! http://www.gnu.org/fun/jokes/ed.msg.html
The hack below was a quick off-the-cuff answer which worked and received lots of upvotes. Then, as the question became more popular and more time passed, outraged people started reporting that it sorta worked but weird things could happen, or it just didn't work at all, so it was furiously downvoted for a time. Such fun.
The solution exploits the exact implementation of file descriptors on your system and, because implementation varies significantly between nixes, it's success is entirely system dependent, definitively non-portable, and should not be relied upon for anything even vaguely important.
Now, with all that out of the way the answer was:
Creating another file descriptor for the file (exec 3<> yourfile
) thence writing to that (>&3
) seems to overcome the read/write on same file dilemma. Works for me on 600K files with awk. However trying the same trick using 'cat' fails.
Passing the prependage as a variable to awk (-v TEXT="$text"
) overcomes the literal quotes problem which prevents doing this trick with 'sed'.
#!/bin/bash
text="Hello world
What's up?"
exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3
John Mee: your method is not guaranteed to work, and will probably fail if you prepend more than 4096 byte of stuff (at least that's what happens with gnu awk, but I suppose other implementations will have similar constraints). Not only will it fail in that case, but it will enter an endless loop where it will read its own output, thereby making the file grow until all the available space is filled.
Try it for yourself:
exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3
(warning: kill it after a while or it will fill the filesystem)
Moreover, it's very dangerous to edit files that way, and it's very bad advice, as if something happens while the file is being edited (crash, disk full) you're almost guaranteed to be left with the file in an inconsistent state.
Not possible without a temp file, but here goes a oneliner
{ echo foo; cat oldfile; } > newfile && mv newfile oldfile
You can use other tools such as ed or perl to do it without temp files.
If you need this on computers you control, install the package "moreutils" and use "sponge". Then you can do:
cat header myfile | sponge myfile
It may be worth noting that it often is a good idea to safely generate the temporary file using a utility like mktemp, at least if the script will ever be executed with root privileges. You could for example do the following (again in bash):
(tmpfile=`mktemp` && { echo "prepended text" | cat - yourfile > $tmpfile && mv $tmpfile yourfile; } )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With