Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

The man page of rm in GNU coreutils 8.12.197-032bb describes the -f or --force option as "ignore nonexistent files, never prompt". Without this option, it will remove any existing files, never prompt, and return a non-zero exit code if any of the specified files did not exist. I'd like to preserve the files if any of the specified files do not exist. What is the easiest way to do this?

The use case is safety: If I'm trying to remove a file which doesn't exist, it could be because there's an invalid expectation (or plain bug) in the command. For example the famous rm -rf /usr /lib/nvidia-current/xorg/xorg could have been averted in many ways, one of them being such an option (obviously unless the user by some incredible coincidence had a /lib/nvidia-current/xorg/xorg directory), and another being to Use More Quotes™. However, quotes aren't always enough. For example, consider ssh host '/bin/rm some paths; /bin/bash foo.sh' - If I had forgotten the semicolon or inserted pretty much any other symbol like colon or comma, it would have tried to remove /bin/bash and ~/foo.sh.

share|improve this question

3 Answers 3

up vote 1 down vote accepted

I use this sort of thing:

mkdir DELETE && mv "some" "paths" DELETE && rm -rf DELETE

For a single path:

mv /some/path DELETE && rm -rf DELETE

Even better, type the rm command on a separate command line: mv /some/path DELETE Enter rm -rf DELETE Enter. That way, the only rm command that makes it into your shell history is on a file called DELETE, so if you removed an old version of a file, you don't risk removing the new version by accidentally pressing Up the wrong number of times then Enter.

If you want to automate a bit:

mv_to_DELETE () {
  mkdir DELETE &&
  mv -- "$@" DELETE/
}
mv_to_DELETE "some" "paths"
rm -rf DELETE
share|improve this answer
    
Nice! Now I just need to use mktemp and a trap to move the files back and delete the temporary directory if the mv fails. –  l0b0 Oct 10 '12 at 7:39

Something like

paths=("some" "paths")
for path in "${paths[@]}"
do
    [ -e "$path" ] || exit 1
done

before each rm command is a lot more complicated for a beginner, and depends on Bash arrays.

share|improve this answer
for path in "some" "paths"
do
    [ -e "$path" ] || exit 1
done

is more portable, but means duplicating the list of paths in the loop and the rm command. And storing all the paths in the same string variable means that the script no longer supports any of the IFS characters in file names.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.