tags:

views:

113

answers:

4

I'm trying to write a bash script that can edit itself. The line of code I'm trying to use is:

sed "s/$STRING_TO_REPLACE/$NEW_STRING/" < $0 > $0

But after running the script I end up with an empty file. Any suggestions?

I am creating a script that has two variables that contain default values. The only problem is, these default values will be different for each of the many stations where it will be used. I would rather none of the people running these stations had to open the script and edit the defaults themselves, so I want to include the ability to change the defaults in the script. One of the requirements I have is that the script must be self contained; no other files are to accompany the script and there are to be no environment variables. This would require the script to be able to edit itself.

+1  A: 

If you want to do an in-place substitution with sed, use the -i switch.

I wouldn't recommend re-writing the currently executing script on the fly. I'm not sure whether it's possible or not, but if it is, it would certainly be interesting (read: difficult) code to maintain :-)

Cameron
I understand that it's ugly. I'll have to think of another way to do this.
Jake Greene
+1  A: 

Firstly, this is a very bad idea and I can't imagine any use case for it that can't be covered by something not this.

The reason this is happening is because when you do >file, it opens the file in read mode and truncates it to 0 length, and the input has nothing to read. You need to use a temp file. You can see more info here.

Daenyth
A: 

Perl handles in place edits. Try this:

perl -npi -e "s/$STRING_TO_REPLACE/$NEW_STRING/g" < $0
Robert Wohlfarth
This won't work because you're giving the file on STDIN so there's no file to in-place modify. Remove the `<` for it to do what you're trying.
Daenyth
+1  A: 

You're trying to read and write to the same stream, this is a bad programming practice and usually results in errors.

This is what you should do:

  1. Write to a temp file
  2. Delete the original file
  3. Rename temp to the original file name

    sed "s/$STRING_TO_REPLACE/$NEW_STRING/" < $0 > temp

    rm $0

    mv temp $1

I haven't done bash scripting in while, so verify that I have the right commands.

MikeAbyss
The rm is not needed, it should be "mv temp $0", and I have to perform chmod at the end to make the new file executable. Other than that it works :) I wasn't aware that I could delete the script while it was running.
Jake Greene