I was writing a bash script, and happened to updated the code (saved the script file to disk) while the script was waiting for some input in a while
loop. After I returned to the terminal and continued with the previous invocation of the script, bash gave an error about the file syntax:
/home/aularon/bin/script: line 58: unexpected EOF while looking for matching `"'
/home/aularon/bin/script: line 67: syntax error: unexpected end of file
So I tried doing the following:
1st: create a script, self-update.sh
let's call it:
#!/bin/bash
fname=$(mktemp)
cat $0 | sed 's/BEFORE\./AFTER!./' > $fname
cp $fname $0
rm -f $fname
echo 'String: BEFORE.';
What the script does is reading its code, changing the word 'BEFORE' into 'AFTER', then re-write itself with the new code.
2nd Run it:
chmod +x self-update.sh
./self-update.sh
3rd wonder...
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.
Now, I wouldn't have guessed that on the same invocation it would output AFTER!, on the second run for sure, but not on the first one.
So my question is: is it intentional (by design)? or it is because of the way bash runs the script? Line by line or command by command. Is there any good use of such behaviour? Any example of it?
Edit: I tried reformatting the file to put all command in one line, it does not work now:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;echo 'String: BEFORE.';
Output:
aularon@aularon-laptop:~$ ./self-update.sh #First invocation
String: BEFORE.
aularon@aularon-laptop:~$ ./self-update.sh #Second invocation
String: AFTER!.
While when moving the echo
string to the next line, separating it from the rewriting (cp
) call:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;
echo 'String: BEFORE.';
And now it works again:
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.