How to reliably remove all temporary files created in a script?
Subshells inherit the environment or some part of it. It looks like when you execute a function in a subshell, you don't need your variables to be exported (compare: No need for export when running functions in subshell). There may be some cases when you need to export
but let's concentrate on your example.
Your approach is flawed and will be hard to maintain because inheritance goes one way. Every (mfunc)
inherits tmp_tmp_files
and works with its own copy of the array. There's no way it could modify the original tmp_tmp_files
used in the main script. Therefore the main script cannot clean everything, it just doesn't possess enough information.
If you choose to clean from the subshelled function then you will need to pay attention and tell apart the temporary files of the function from the temporary files of the main script. Prematurely removing the latter may cause your script to fail.
Alternative approach: a temporary directory
-
Instead of creating an array, create a directory and remember its path. Do it once in the beginning and
export
if you need:tempdir=$(mktemp -d mscript.XXXXXXXXXX)
-
Create every temporary file within the temporary directory, like this:
tempfile=$(mktemp -p "$tempdir")
-
At the end remove the entire directory, no matter whether the particular files were created by the main script or by a subshell, or even by some stray third-party program. You may use a trap to perform this step. Simply:
rm -r "$tempdir"
Related videos on Youtube
kaligne
Updated on September 18, 2022Comments
-
kaligne over 1 year
Is it possible to trap the exit/return of a function? For a program I could do
trap -- "clean_this" EXIT
That would execute the function
clean_this
when the program exits. I would like to do something of the sort when exiting from a function.function myfunc() { echo "I'm a function" } myfunc & wait $!
I execute the function in a subshell, and I'd like to trap it's exit/return. Is that possible?
EDIT1
Here is my purpose
I have one script supposed to manage temporary files:
cat tempfiles.sh ## List of temp files tmp_tmp_files=() ## Adds a file to the list of temp files function tmp_add_file() { tmp_tmp_files+=("$1") } ## Resets the list of temp files function tmp_reset_files() { tmp_tmp_files=() } ## Removes the list of temp files function tmp_rm_all() { rm -f "${tmp_tmp_files[@]}" } ## Removes all temp files on exit and sigint trap "tmp_rm_all" EXIT SIGINT
Here is my main script:
cat mscript.sh source tempfiles.sh ## ## Creates a temp file and writes in it mfunc() { local tempfile=$(mktemp) tmp_add_file $tempfile echo "something" >> $tempfile echo "($BASHPID) - tempfiles: ${tmp_tmp_files[@]}" } ## Creates a temp file in main shell mfunc ## Creates a temp file in a subshell (mfunc)
I call the main script:
$ bash mscript.sh (92250) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj (92254) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq
I check the temp files:
$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj cat: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj: No such file or directory $ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq something
The temp files declared in the
subshell
are lost from the list when exiting the program. I would like to have them removed ideally at the end of the function. Either I have to specifically remove them before leaving the function, it is easy and it costs me one more line:mfunc() { local tempfile=$(mktemp) tmp_add_file $tempfile1 echo "something" >> $tempfile echo "tempfiles: ${tmp_tmp_files[@]}" ## Process things... rm $tempfile1 }
But I'd like to know if there is an elegant way to have them (the temp files created in the
subshells
) removed automatically, like I do withtrap
s when exiting the program.So my question is: is it possible to do it? What could be some alternatives?
-
Kamil Maciorowski almost 7 yearsWhat are you trying to achieve? Function put to background can call another function, so let
myfunc
callclean_this
at the very end. Or invoke them like{ myfunc ; clean_this ; } &
. Do you really need a trap? -
kaligne almost 7 yearsThanks for replying. Here I edited my question and wrote my purpose. Well surely I can avoid traps, but since I started using them, if I can do what I want in an easy way... Why not
-
-
kaligne almost 7 yearsthanks that's what I do for now. So, I take it there is no way to trigger anything as soon as a function stops. Right?
-
Kamil Maciorowski almost 7 years@user3298319 I don't know for sure. It so happened your question was the XY problem and I answered to solve your actual problem. I also changed the title, so now it's not useful for users interested in traps; it's useful in the topic of temporary files. My point is: this question has evolved. If you want to research traps, you may ask another question and explain there that you're asking out of curiosity. This may not be well received though. The site concentrates on solving practical problems and users tend to hand you proper tools as I did.