Can a shell script delete or overwrite itself?

Is this a curiosity you have or what you actually want to obtain?

Anyway, I've tried myself this simple script (test_script.sh):

rm -f test_script.sh
echo "Still here!"

and it prints Still here!, so the file was loaded before execution. Execution is not possible the second time.

To answer your question, yes and no. The commands in the script are loaded and executed, and can delete the source file of the script. This will make impossible to execute the same file again, of course, but will not affect the first execution.


On Unix-like operating systems, removing a file is possible if it is still open. The file name will no longer exist, but the data itself does remain, and any programs that have an open handle, including bash, can continue to read (and even write) using that handle. Only when the last program closes its handle does the file really get deleted.

So, in a sense, yes, a shell script can delete itself, but it won't really be deleted until after the execution of that script finishes.

Note that you get different results if you overwrite the file instead of deleting it. Shells may (and do) use buffering to avoid reading one byte at a time, but the buffer has a finite size. If the file contents change beyond what the shell has already read into memory, it will see the new content. You can create a simple example of this if you examine what the buffer size for your system is. On my system, it happens to be 8 KiB. So a shell script that contains

echo line 1
>test.sh
# (8167 random characters)
echo line 4

so the second block of data is "cho line 4", on my system, outputs

$ bash test.sh
line 1
test.sh: line 4: e: command not found

because the e has already been read, and the shell encountered EOF when trying to read the rest of the line.

Update: rici shows that with a different example of overwriting the file, the newly written contents do get used. Reworking that:

script="`tr 12 21 <test.sh`"
env echo "$script" >test.sh
echo toggle: 1

The second line intentionally doesn't use bash's built-in echo command, because that sometimes doesn't cause bash to re-read the script, per the comments, but precisely when it does and doesn't is unclear to me. bash outputs the newly written toggle value when it gets to line three. The relevant difference between this and my earlier example seems to be that here, bash can seek to the current position when it gets to line three, whereas in my earlier example, that is impossible, because that position no longer exists, as the file is empty.

Tags:

Bash