使用传递给脚本的用户名,find用户的主目录

我正在写一个脚本,当用户login时会被调用,并检查某个文件夹是否存在,或者是一个破碎的符号链接。 (这是在Mac OS X系统上,但问题纯粹是bash)。

这不是优雅的,它不工作,但现在看起来像这样:

#!/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." 

问题的关键在于代字符扩展不能按我的意愿工作。

让我们说,我有一个名为george的用户,他的home文件夹是/a/path/to/georges_home 。 如果在一个shell中,我input:

 cd ~george 

它把我带到适当的目录。 如果我input:

 HOME_DIR=~george echo $HOME_DIR 

它给了我:

 /a/path/to/georges_home 

但是,如果我尝试使用一个variables,它不起作用:

 USERNAME="george" cd ~$USERNAME -bash: cd: ~george: No such file or directory 

我试过使用引号和反引号,但不知道如何使其正确扩展。 我该如何做这项工作?


附录

我只是想发布我的完整的脚本(实际上,它不像上面的工作那样丑陋!)并且说它似乎是正确的。

 #!/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 

使用$(eval echo ...)

 michael:~> USERNAME=michael michael:~> echo ~michael /home/michael michael:~> echo ~$USERNAME ~michael michael:~> echo $(eval echo ~$USERNAME) /home/michael 

所以你的代码应该是这样的:

 HOMEDIR="$(eval echo ~$USERNAME)" 

这是因为它将设置为variables时将〜george放在单引号内。 set -x对debugging很有用。

设置DIR时删除引号,当设置variables时,shell会扩展,这会给你想要的性能。

 lrwxrwxrwx 1 root root 4 Sep 10 2004 /bin/sh -> bash* wmoore@bitbucket(/tmp)$ cat test.sh #!/bin/bash set -x cd ~root DIR=~root cd $DIR DIR="~root" cd $DIR wmoore@bitbucket(/tmp)$ sh test.sh + cd /root test.sh: line 4: cd: /root: Permission denied + DIR=/root + cd /root test.sh: line 8: cd: /root: Permission denied + DIR=~root + cd '~root' test.sh: line 12: cd: ~root: No such file or directory 

Bash内置了导出的用户名和用户主目录的variables。 例如,如果用户在从~/.bash_profilelogin时调用脚本,则不需要将值作为parameter passing给脚本。

您可以使用$USER$HOME因为它们已经在脚本环境中设置并可用,因为它们被标记为已导出。 我认为代字符扩展比在脚本中使用的东西更像是命令行方便。

 DIR="$HOME/Library/Caches" cd "$DIR" || rm "$DIR" && echo "Removed misdirected Cache folder" && exit 1 

以下列方式之一获取用户的主目录可能更加可靠:

 getent passwd $USER | awk -F: '{print $(NF - 1)}' 

要么

 awk -F: -v user=$USER 'user == $1 {print $(NF - 1)}' /etc/passwd 

另外, exit 0表示成功。 某种程度上,你的程序在删除目录时是成功的,但是它需要删除的事实是一个错误。 在任何情况下,如果此时exit 0 ,那么当脚本在最后的echo后退出时,您将无法区分差异,因为退出代码很可能为零。

从path$HOME/Library/Caches判断,这是Mac OS X,所以dscl是你的朋友。

如上所述, bash为你做,但如果它是一个Mac,你可以保证bash将可用(所以你不必担心严格符合/bin/sh无法应付它)。