I am writing a script that gets called when a user logs in and check if a certain folder exists or is a broken symlink. (This is on a Mac OS X system, but the question is purely bash).
It is not elegant, and it is not working, but right now it looks like this:
#!/bin/bash
# Often users have a messed up cache folder -- one that was redirected
# but now is just a broken symlink. This script checks to see if
# the cache folder is all right, and if not, deletes it
# so that the system can recreate it.
USERNAME=$3
if [ "$USERNAME" == "" ] ; then
echo "This script must be run at login!" >&2
exit 1
fi
DIR="~$USERNAME/Library/Caches"
cd $DIR || rm $DIR && echo "Removed misdirected Cache folder" && exit 0
echo "Cache folder was fine."
The crux of the problem is that the tilde expansion is not working as I'd like.
Let us say that I have a user named george
, and that his home folder is /a/path/to/georges_home
. If, at a shell, I type:
cd ~george
it takes me to the appropriate directory. If I type:
HOME_DIR=~george
echo $HOME_DIR
It gives me:
/a/path/to/georges_home
However, if I try to use a variable, it does not work:
USERNAME="george"
cd ~$USERNAME
-bash: cd: ~george: No such file or directory
I've tried using quotes and backticks, but can't figure out how to make it expand properly. How do I make this work?
Addendum
I just wanted to post my completed script (really, it isn't as ugly as the work in progress above!) and say that it appears to be working right.
#!/bin/bash
# Often users have a messed up cache folder -- one that was redirected
# but now is just a broken symlink. This script checks to see if
# the cache folder is all right, and if not, deletes it
# so that the system can recreate it.
#set -x # turn on to help debug
USERNAME=$3 # Casper passes the user name as parameter 3
if [ "$USERNAME" == "" ] ; then
echo "This script must be run at login!" >&2
exit 1 # bail out, indicating failure
fi
CACHEDIR=`echo $(eval echo ~$USERNAME/Library/Caches)`
# Show what we've got
ls -ldF "$CACHEDIR"
if [ -d "$CACHEDIR" ] ; then
# The cache folder either exists or is a working symlink
# It doesn't really matter, but might as well output a message stating which
if [ -L "$CACHEDIR" ] ; then
echo "Working symlink found at $CACHEDIR was not removed."
else
echo "Normal directory found at $CACHEDIR was left untouched."
fi
else
# We almost certainly have a broken symlink instead of the directory
if [ -L "$CACHEDIR" ] ; then
echo "Removing broken symlink at $CACHEDIR."
rm "$CACHEDIR"
else
echo "Abnormality found at $CACHEDIR. Trying to remove." >&2
rm -rf "$CACHEDIR"
exit 2 # mark this as a bad attempt to fix things; it isn't clear if the fix worked
fi
fi
# exit, indicating that the script ran successfully,
# and that the Cache folder is (almost certainly) now in a good state
exit 0
Use
$(eval echo ...)
:So your code should look like:
It's because it's going to enclose the ~george within singlequotes when set as a variable.
set -x
is useful for debugging.Remove the quoting when setting
DIR
and the shell will expand when setting the variable, which will give you your desired performance.Bash has built-in exported variables for username and user's home directory. If you are calling your script when the user logs in from their
~/.bash_profile
for example, you won't need to pass the values as arguments to your script.You can use
$USER
and$HOME
since they're already set and available in the environment of your script since they're marked as exported. I think tilde expansion is meant to be more of a command-line convenience than something that's used in scripts.It might be more reliable to get the user's home directory in one of the following ways:
or
Also,
exit 0
indicates success. In a way, your process is successful in deleting the directory, but the fact that it needs deleting is an error of a sort. In any case, if youexit 0
at this point you won't be able to tell the difference when the script exits after the finalecho
since the exit code there will most likely be zero.Judging by the path
$HOME/Library/Caches
, this is Mac OS X, sodscl
is your friend.As noted above,
bash
does it for you, though, and if it’s a Mac, you can guaranteebash
will be available (and so you don’t need to worry about a strictly-conforming/bin/sh
not being able to cope with it).