Я пишу скрипт, который вызывается, когда пользователь входит в систему и проверяет, существует ли определенная папка или она не работает. (Это в системе 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
и его домашняя папка /a/path/to/georges_home
. Если на оболочке я наберу:
cd ~george
он доставит меня в соответствующий каталог. Если я наберу:
HOME_DIR=~george
echo $HOME_DIR
Это дает мне:
/a/path/to/georges_home
Однако, если я пытаюсь использовать переменную, она не работает:
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
Это потому, что он собирается заключить ~ george в одинарные кавычки, когда он установлен в качестве переменной.
set -x
полезно для отладки.Удалите кавычки при установке,
DIR
и оболочка расширится при установке переменной, что даст вам желаемую производительность.источник
Bash имеет встроенные экспортируемые переменные для имени пользователя и домашнего каталога пользователя. Если вы вызываете ваш скрипт, когда пользователь входит в систему,
~/.bash_profile
например, из его , вам не нужно передавать значения в качестве аргументов вашему скрипту.Вы можете использовать
$USER
и$HOME
так как они уже установлены и доступны в среде вашего скрипта, так как они помечены как экспортированные. Я думаю, что расширение тильды предназначено для большего удобства командной строки, чем то, что используется в скриптах.Может быть более надежным получить домашний каталог пользователя одним из следующих способов:
или
Также
exit 0
указывает на успех. В некотором смысле, ваш процесс успешно удаляет каталог, но тот факт, что он требует удаления, является своего рода ошибкой. В любом случае, если выexit 0
в этот момент не сможете определить разницу, когда скрипт выйдет после финала,echo
так как код выхода там, скорее всего, будет нулевым.источник
||
и&&
как управление потоком (замена операторов if) в плохом стиле.exit n
в конце скрипта, если провал также является ошибкой. Ноль означает успех, и вы можете использовать разные ненулевые числа для указать различные типы ошибок (это зависит от вас, чтобы определить их значение для ваших собственных целей.) Если вам не нужно отличать один тип ошибки от другого, тоexit 1
лучше использовать любой во всех случаях для указания общая ошибка.Судя по пути
$HOME/Library/Caches
, это Mac OS X,dscl
как и ваш друг.Как уже отмечалось выше,
bash
он делает это для вас, и, если это Mac, вы можете гарантировать, чтоbash
он будет доступен (и поэтому вам не нужно беспокоиться о том, что вы/bin/sh
не сможете с этим справиться).источник
dscl /Search read /Users/$USERNAME NFSHomeDirectory | cut -f 2 -d " "
Похоже, что это правильно для получения информации, которую я получил.