This is probably a complex solution.
I am looking for a simple operator like ">>", but for prepending.
I am afraid it does not exist. I'll have to do something like
mv $F tmp cat header tmp > $F
Anything smarter? (I am not fond of tmp files)
This is probably a complex solution.
I am looking for a simple operator like ">>", but for prepending.
I am afraid it does not exist. I'll have to do something like
mv $F tmp cat header tmp > $F
Anything smarter? (I am not fond of tmp files)
This still uses a temp file, but at least it is on one line:
echo "text"|cat - yourfile > /tmp/out && mv /tmp/out yourfile
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.
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; } )
When you start trying to do things that become difficult in shell-script, I would strongly suggest looking into rewriting the script in a "proper" scripting language (Python/Perl/Ruby/etc)
As for prepending a line to a file, it's not possible to do this via piping, as when you do anything like cat blah.txt | grep something > blah.txt
, it inadvertently blanks the file. There is a small utility command called sponge
you can install (you do cat blah.txt | grep something | sponge > blah.txt` and it buffers the contents of the file, then writes it to the file), but I would say that's a "worse" requirement than, say, Perl.
There may be a way to do it via awk, or similar, but if you have to use shell-script, I think a temp file is by far the easiest(/only?) way..
No temp files.
One line solution.
Prepend whatever you like.
#!/bin/bash
text="Hello world
What's up?"
exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3
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 nuisance that hinders 'sed'.
assuming that the file you want to edit is my.txt
$cat my.txt
this is the regular file
And the file you want to prepend is header
$ cat header
this is the header
Be sure to have a final blank line in the header file.
Now you can prepend it with
$cat header <(cat my.txt) > my.txt
You end up with
$ cat my.txt
this is the header
this is the regular file
As far as I know this only works in 'bash'.
A variant on cb0's solution for "no temp file" to prepend fixed text:
echo "text to prepend" | cat - file_to_be_modified | ( cat > file_to_be_modified )
Again this relies on sub-shell execution - the (..) - to avoid the cat refusing to have the same file for input and output.
Bah! No one cared to mention about tac.
endor@grid ~ $ tac --help
Usage: tac [OPTION]... [FILE]...
Write each FILE to standard output, last line first.
With no FILE, or when FILE is -, read standard input.
Mandatory arguments to long options are mandatory for short options too.
-b, --before attach the separator before instead of after
-r, --regex interpret the separator as a regular expression
-s, --separator=STRING use STRING as the separator instead of newline
--help display this help and exit
--version output version information and exit
Report tac bugs to [email protected]
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
Report tac translation bugs to <http://translationproject.org/team/>
current=cat my_file
&& echo 'my_string' > my_file && echo $current >> my_file
where "my_file" is the file to prepend "my_string" to.
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.
echo '0a
your text here
.
w' | ed some_file
ed is the Standard Editor! http://www.gnu.org/fun/jokes/ed.msg.html
The workaround to the overwrite problem is using tee
:
cat header main | tee main > /dev/null