Estou escrevendo um script chamado quando um usuário efetua login e verifica se existe uma determinada pasta ou se há um link simbólico quebrado. (Isso ocorre em um sistema Mac OS X, mas a pergunta é puramente básica).
Não é elegante e não está funcionando, mas agora parece com isso:
#!/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."
O cerne do problema é que a expansão til não está funcionando como eu gostaria.
Digamos que eu tenha um usuário chamado george
e que seja sua pasta pessoal /a/path/to/georges_home
. Se, em um shell, eu digitar:
cd ~george
isso me leva ao diretório apropriado. Se eu digitar:
HOME_DIR=~george
echo $HOME_DIR
Isso me dá:
/a/path/to/georges_home
No entanto, se eu tentar usar uma variável, ela não funcionará:
USERNAME="george"
cd ~$USERNAME
-bash: cd: ~george: No such file or directory
Tentei usar aspas e backticks, mas não consigo descobrir como fazê-lo expandir adequadamente. Como eu faço isso funcionar?
Termo aditivo
Eu só queria postar meu script completo (realmente, não é tão feio quanto o trabalho em andamento acima!) E dizer que ele parece estar funcionando corretamente.
#!/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
É porque ele irá colocar o ~ george entre aspas simples quando definido como uma variável.
set -x
é útil para depuração.Remova a citação ao definir
DIR
e o shell se expandirá ao definir a variável, o que fornecerá o desempenho desejado.fonte
O Bash incorporou variáveis exportadas para o nome de usuário e o diretório inicial do usuário. Se você estiver chamando seu script quando o usuário fizer login,
~/.bash_profile
por exemplo, não será necessário passar os valores como argumentos para o seu script.Você pode usar
$USER
e,$HOME
já que eles já estão definidos e disponíveis no ambiente do seu script, pois estão marcados como exportados. Eu acho que a expansão til deve ser mais uma conveniência da linha de comando do que algo usado em scripts.Pode ser mais confiável obter o diretório inicial do usuário de uma das seguintes maneiras:
ou
Além disso,
exit 0
indica sucesso. De certa forma, seu processo foi bem-sucedido ao excluir o diretório, mas o fato de ele precisar ser excluído é um erro de uma classificação. De qualquer forma, se vocêexit 0
não apontar a diferença quando o script sair após a final,echo
já que o código de saída provavelmente será zero.fonte
||
e&&
como o controle de fluxo (substituindo as instruções if) são ruins.exit n
no final do script, se cair também for um erro. Zero indica sucesso e você pode usar números diferentes de zero para indicar tipos diferentes de erros (depende de você determinar o significado deles para seus próprios propósitos) .Se você não precisar distinguir um tipo de erro de outro,exit 1
será tão bom quanto qualquer outro usar em todos os casos para indicar um erro. erro geral ..A julgar pelo caminho
$HOME/Library/Caches
, este é o Mac OS X, assimdscl
como seu amigo.Como mencionado acima, você
bash
faz isso para você e, se for um Mac, você pode garantirbash
que estará disponível (e assim você não precisa se preocupar com o fato de/bin/sh
não conseguir lidar com isso).fonte
dscl /Search read /Users/$USERNAME NFSHomeDirectory | cut -f 2 -d " "
parece estar certo para obter as informações que eu estava procurando.