J'écris un script qui est appelé lorsqu'un utilisateur se connecte et vérifie si un certain dossier existe ou s'il s'agit d'un lien symbolique cassé. (C'est sur un système Mac OS X, mais la question est purement bash).
Ce n'est pas élégant et cela ne fonctionne pas, mais en ce moment, cela ressemble à ceci:
#!/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."
Le nœud du problème est que l'expansion du tilde ne fonctionne pas comme je le voudrais.
Disons que j'ai un utilisateur nommé george
et que son dossier de départ est /a/path/to/georges_home
. Si, sur un shell, je tape:
cd ~george
cela m'amène au répertoire approprié. Si je tape:
HOME_DIR=~george
echo $HOME_DIR
Ça me donne:
/a/path/to/georges_home
Cependant, si j'essaie d'utiliser une variable, cela ne fonctionne pas:
USERNAME="george"
cd ~$USERNAME
-bash: cd: ~george: No such file or directory
J'ai essayé d'utiliser des guillemets et des astuces, mais je n'arrive pas à comprendre comment le développer correctement. Comment faire pour que ça marche?
Addenda
Je voulais juste publier mon script terminé (vraiment, ce n'est pas aussi moche que le travail en cours ci-dessus!) Et dire qu'il semble fonctionner correctement.
#!/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
C'est parce que cela va enfermer le ~ george dans des guillemets simples lorsqu'il est défini comme une variable.
set -x
est utile pour le débogage.Supprimez les guillemets lors de la définition
DIR
et le shell se développera lors de la définition de la variable, ce qui vous donnera les performances souhaitées.la source
Bash a intégré des variables exportées pour le nom d'utilisateur et le répertoire personnel de l'utilisateur. Si vous appelez votre script lorsque l'utilisateur se connecte à partir de leur
~/.bash_profile
par exemple, vous n'aurez pas besoin de passer les valeurs comme arguments à votre script.Vous pouvez utiliser
$USER
et$HOME
puisqu'ils sont déjà définis et disponibles dans l'environnement de votre script car ils sont marqués comme exportés. Je pense que l'expansion du tilde est censée être plus pratique en ligne de commande que quelque chose qui est utilisé dans les scripts.Il peut être plus fiable d'obtenir le répertoire personnel de l'utilisateur de l'une des manières suivantes:
ou
En outre,
exit 0
indique le succès. D'une certaine manière, votre processus réussit à supprimer le répertoire, mais le fait qu'il doive être supprimé est une erreur en quelque sorte. Dans tous les cas, si vousexit 0
à ce stade, vous ne pourrez pas faire la différence lorsque le script se terminera après la finale,echo
car le code de sortie sera probablement nul.la source
||
et&&
que le contrôle de flux (remplacer les instructions if) est un mauvais style.exit n
à la fin du script si l'échec est également une erreur. Zéro indique le succès et vous pouvez utiliser différents nombres non nuls pour indiquer différents types d'erreurs (c'est à vous de déterminer leur signification pour vos propres besoins). Si vous n'avez pas besoin de distinguer un type d'erreur d'un autre, ilexit 1
est aussi bon que n'importe quel à utiliser dans tous les cas pour indiquer un erreur générale.À en juger par le chemin
$HOME/Library/Caches
, c'est Mac OS X,dscl
votre ami aussi.Comme indiqué ci-dessus, le
bash
fait pour vous, et s'il s'agit d'un Mac, vous pouvez garantirbash
qu'il sera disponible (et vous n'avez donc pas à vous soucier d'un strict conforme/bin/sh
ne pouvant pas y faire face).la source
dscl /Search read /Users/$USERNAME NFSHomeDirectory | cut -f 2 -d " "
semble être à peu près juste pour obtenir les informations que je recherchais.