/usr/home and /home

I was putting together a script and probably got a little lazy and started using /home/ instead of /usr/home in variables. I clean up temporary files at the end of the script and almost fell off my chair when the script wanted to delete from /. Can anyone shed some light on this or should I just let it go?

Rich (BB code):
variable1=/home/example1
variable2=/usr/home/example2

 rm $variable1/* = Really bad
 rm $variable2/* = Okay
 
What are you trying to accomplish? You cannot tell me that this is a regular case that every file in a user's home directory is a temporary file.

In my opinion both commands are really bad in a script. Whatever you do with this script, it looks like you will lose important data sooner or later.
 
Both should do exactly the same, I see absolutely no reason why rm /home/somedir/* would behave differently from rm /usr/home/somedir/* unless /home isn't a symlink to /usr/home.
 
jetoblaster said:
rm $variable1/* = Really bad
rm $variable2/* = Ok

Just from experience, avoid using variables as a prefix like that. If $variable is undefined, it will do it on / just as you say. You will have a very unhappy day if you accidentally run this as root. Instead consider something like: rm $variable/example/*. If $variable is undefined, it still goes to /example/* which will error out since it doesn't exist.

cd $variable/example/ || exit is also useful.
 
nakal said:
What are you trying to accomplish? You cannot tell me that this is a regular case that every file in a user's home directory is a temporary file.

In my opinion both commands are really bad in a script. Whatever you do with this script, it looks like you will lose important data sooner or later.
It was just an example; I do not delete every file in the user's home directory, it's a subdirectory with temporary files.

SirDice said:
Both should do exactly the same, I see absolutely no reason why rm /home/somedir/* would behave differently from rm /usr/home/somedir/* unless /home isn't a symlink to /usr/home.
You're right.

Jeckt said:
Just from experience, avoid using variables as a prefix like that. If $variable is undefined, it will do it on / just as you say. You will have a very unhappy day if you accidentally run this as root. Instead consider something like:

rm $variable/example/*

If $variable is undefined, it still goes to /example/* which will error out since it doesn't exist.

cd $variable/example/ || exit

is also useful.
You are 100% correct, it was a typo in the command, the variable therefore did not exist which is why it tried to delete /. Thank you, I will be more careful in the future. On a side note since I only use rm and not rm -R it couldn't delete anything apart from two symbolic links.
 
Last edited by a moderator:
This question was answered a while ago, but here's some information on how to prevent this sort of errors, or at least limit their potentially dangerous scope.

set -u is your friend; from sh(1):

Code:
-u nounset
    Write a message to standard error when attempting to expand a vari‐
    able, a positional parameter or the special parameter ! that is not
    set, and if the shell is not interactive, exit immediately.

Example usage:
Code:
[~]% cat u-test.sh
#!/bin/sh

set -u

var=/usr
echo "$var/home"
echo "$undefined/home"

[~]% sh u-test.sh
/usr/home
u-test.sh: undefined: parameter not set
Exit 2

This won't protect you from all typos, though, consider: rm -rf /usr/ $myapp. Can you spot the error? ;)

To circumvent this, always, and I mean, ALWAYS, quote path names. I believe it was BitlBee who got this wrong in one of their releases a few years ago (the exact same error as above, an accidental space), and make uninstall would remove /usr; that's one way to uninstall it I suppose... (I can't find it right now though).

Code:
# Still not correct, but won't clobber your entire system
rm -rf "/usr $myapp"

Adding quotes is also a good reason because sooner or later your file name will contain a space (or any other "strange character"; UNIX file systems can have any character except the null byte), at which point it all breaks down.

So remember:
  1. Always use set -u.
  2. Always quote pathnames.
 
Back
Top