this post was submitted on 20 Sep 2026
21 points (95.7% liked)

Programming

28875 readers
461 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 3 years ago
MODERATORS
 

Update: Here is my current corrected version (do not trust blindly, I had typos involved too!)

#!/usr/bin/env bash

TEMPDIR="$(mktemp -d)"
mkdir --verbose -- "${TEMPDIR}/tests"
trap 'cd -- "${TEMPDIR}/tests" && rm --verbose --one-file-system -rf "${TEMPDIR:-/invalid/615e1a5d}/tests"; cd ..; rmdir --verbose -- "${TEMPDIR}"' EXIT

And an alternative variant in case there are only files without subdirectories involved under "tests":

trap 'cd -- "${TEMPDIR}/tests" && rm --verbose --one-file-system -f -- "${TEMPDIR:-/invalid/615e1a5d}/tests/"*; cd ..; rmdir --verbose -- tests "${TEMPDIR}"' EXIT

Note, I use --verbose to explicitly list files, because this is for my Test system. If you copy this construct to use in your own normal scripts, you might want to remove the verbose flags for normal usage.


Down below is old version:

This is just a little small question if this is secure. This script is used to create a fresh test environment that should get deleted when script ends. trap command solves that issue fine. However, I am very, very afraid of doing rm -rf in context of variables, in case the variable happens to become empty due to user error (or later changes in script). So I will do this in multiple steps.

#!/usr/bin/env bash

TEMPDIR="$(mktemp -d)"
mkdir -f -- "${TEMPDIR}/tests"
trap 'cd -- "${TEMPDIR}/tests" && rm -rf tests && cd .. && rmdir -- ${TEMPDIR}' EXIT

# Here follows the script content, creating temporary files and manipulating them...
  1. Use a subdirectory, so the variable is not used by itself. So we have to use ${TEMPDIR}/tests each time instead just ${TEMPDIR}.
  2. When removing all files recursively, first enter into directory with cd, and only if that was successful delete all files recursively with a specific directory name. This should make sure that rm -rf is only executed if the temporary directory even exist and the variable is not resolved to empty.
  3. Off course go up one dir again and then remove the empty directory with rmdir, which will only remove empty directories.

I personally feel confident that this construct is safe, but would like to hear your opinions. Maybe I missed something important. It would be devastating. I don't want to try out various ways to see if one of them is working correctly.


Edit: For anyone who does not create uncontrolled temporary directories, they could just use rm -f tests/* instead, so nothing is deleted recursively. I may go that route and avoid sub-directories in my test folder.

you are viewing a single comment's thread
view the rest of the comments
[–] TehPers@beehaw.org 1 points 4 weeks ago* (last edited 4 weeks ago) (1 children)

With Bash, you'll only ever get "good enough" solutions. Even with your current setup, it's susceptible to a race condition where another process adds to the TEMPDIR directory some other way during the script, and potentially even recreates tests after you delete it and before you remove the parent directory.

Usually with Bash, the most readable solution is the best. I'd recommend a simple test for $TEMPDIR existing before a simple rm -rf "$TEMPDIR".

However, I am very, very afraid of doing rm -rf in context of variables, in case the variable happens to become empty due to user error (or later changes in script).

In this case, just test for this? Test that the variable is not empty and that the directory exists, then rm -rf the directory. No need to overcomplicate it.

[–] thingsiplay@lemmy.ml 0 points 4 weeks ago (1 children)

it’s susceptible to a race condition where another process adds to TEMPDIR some other way during the script, and potentially even recreates tests after you delete it and before you remove the parent directory.

You mean a subprocess from this script? In that case, the variable $TEMPDIR is never changed from the perspective of the script. Because its not exposed to subprocesses and the name is totally random by mktemp. So I don't see how a subprocess should be able to do that.

Usually with Bash, the most readable solution is the best. I’d recommend a simple test for $TEMPDIR existing before a simple rm -rf "$TEMPDIR".

This is what I want to avoid. Because what if I make mistakes in my own script and reassign $TEMPDIR by accident in a loop, instead reading from it. So at the time of execution of rm -rf, there is a chance that $TEMPDIR could potentially point to a different directory in example.

[–] TehPers@beehaw.org 1 points 4 weeks ago (1 children)

So I don't see how a subprocess should be able to do that.

I'm referring to any process being able to do that, subprocess or not. If you know that no process on the system can interfere with your directory in any way, then you can be confident that nothing else will touch it.

Because what if I make mistakes in my own script and reassign $TEMPDIR by accident in a loop, instead reading from it. So at the time of execution of rm -rf, there is a chance that $TEMPDIR could potentially point to a different directory in example.

Create another variable for use in the script, and only use $TEMPDIR for creating and deleting the directory then. As long as you are certain you don't reassign it, then you know the value won't change, and you can use a second variable to ensure you don't do that by accident.

[–] thingsiplay@lemmy.ml 0 points 4 weeks ago (1 children)

I’m referring to any process being able to do that, subprocess or not. If you know that no process on the system can interfere with your directory in any way, then you can be confident that nothing else will touch it.

But how should any process know the variable of my script? mktemp makes sure its 100% random. And any process on the system can't just read the variable out.

[–] TehPers@beehaw.org 0 points 4 weeks ago (1 children)

But how should any process know the variable of my script?

Processes can touch any directory they have access to. There can be any number of reasons that a process might do this, from antivirus software (which somehow exists on Linux) to search software leaving index files everywhere to something that just for some reason modifies random directories. My point was that Bash can't guarantee that none of this ever happens, though rm -rf "$TEMPDIR" would get around that and delete the directory anyway (and any lingering contents).

Since you only seem to be worried about accidentally deleting the wrong directory due to mistakes while presumably debugging, this isn't really as relevant as I was suspecting it was. For something more robust though, I'd normally recommend a recursive delete without following any links (in case something links to files you don't want to delete, like ~ or something).

[–] thingsiplay@lemmy.ml 0 points 4 weeks ago* (last edited 4 weeks ago)

In case any process deletes files or the directory "$TEMPDIR" points to, the script should be covered, right? With cd -- "${TEMPDIR}/tests" it is guaranteed that the directory exists when running rm -rf command. And in case the "$TEMPDIR" variable is altered in any way (replaced or added home, ~ or any relative paths like ../../../home in example), at least having a hardcoded directory name with "tests" would make sure it never deletes anything under any circumstances that is not named "tests".

Unless symbolic links and other link files are involved and added to that directory.