I am using sed in a script to do a replace and I want to have the replaced file overwrite the file. Normally I think that you would use this:
% sed -i 's/cat/dog/' manipulate
sed: illegal option -- i
However as you can see my sed does not have that command.
I tried this:
% sed 's/cat/dog/' manipulate > manipulate
But this just turns manipulate into an empty file (makes sense).
This works:
% sed 's/cat/dog/' manipulate > tmp; mv tmp manipulate
But I was wondering if there was a standard way to redirect output into the same file that input was taken from.
Kernighan and Pike in The Art of Unix Programming discuss this issue. Their solution is to write a script called
overwrite
, which allows one to do such things.The usage is:
overwrite
file
cmd
file
.Once you have the above script in your
$PATH
, you can do:To make your life easier, you can use
replace
script from the same book:Having
replace
in your$PATH
too will allow you to say:I commonly use the 3rd way, but with an important change:
$ sed 's/cat/dog/' manipulate > tmp && mv tmp manipulate
I.e. change
;
to&&
so the move only happens if sed is successful; otherwise you'll lose your original file as soon as you make a typo in your sed syntax.Note! For those reading the title and missing the OP's constraint "my sed doesn't support
-i
": For most people, sed will support-i
, so the best way to do this is:$ sed -i 's/cat/dog/' manipulate
Yes,
-i
is also supported in FreeBSD/MacOSXsed
, but needs the empty string as an argument to edit a file in-place.Perhaps
-i
is gnu sed, or just an old version of sed, but anyways. You're on the right track. The first option is probably the most common one, the third option is if you want it to work everywhere (including solaris machines)... :) These are the 'standard' ways of doing it.A lot of answers, but none of them is correct. Here is the correct and simplest one:
If you don't want to move copies around, you could use ed: