Estou curioso por que não podemos mudar para o diretor de casa de um usuário com
$ cd ~"$USER"
ou
$ cd ~${USER}
Estou curioso por que não podemos mudar para o diretor de casa de um usuário com
$ cd ~"$USER"
ou
$ cd ~${USER}
Respostas:
Isso depende muito da concha e da ordem em que as expansões são feitas nessas conchas.
~$userexpande para o diretório inicial do usuário cujo nome está armazenado em $usercsh (de onde esse ~userrecurso vem), AT&T ksh, zsh, fish.
Observe, no entanto, estas variações:
$ u=daemon/xxx csh -c 'echo ~$u'
/usr/sbin/xxx # same in zsh/fish
$ u=daemon/xxx ksh93 -c 'echo ~$u'
~daemon/xxx
$ u=daemon/xxx csh -c 'echo ~"$u"'
Unknown user: daemon/xxx.
$ u=daemon/xxx zsh -c 'echo ~"$u"'
/usr/sbin/x # same in fish
$ u=" daemon" csh -c 'echo ~$u'
/home/stephane daemon
$ u=" daemon" zsh -c 'echo ~$u'
~ daemon # same in ksh/fish
$ u="/daemon" csh -c 'echo ~$u'
/home/stephane/daemon # same in zsh
$ u="/daemon" fish -c 'echo ~$u'
~/daemon # same in ksh
Ele se expande para o diretório inicial do usuário nomeado literalmente $userem bash(desde que o usuário exista, o que é muito improvável, é claro).
E nem em pdksh, dash, yash, presumivelmente porque eles não consideram $userser um nome de usuário válido.
A expansão do til é uma etapa separada no processamento da linha de comando. Isso acontece pouco antes da expansão variável.
Se o til for seguido por algo que não seja uma barra, ele será expandido para o diretório inicial do usuário cujo nome está seguindo o til, como em, por exemplo ~otheruser. Como $USERnão é expandido nesse ponto e como é improvável que corresponda a um nome de usuário válido, o til fica inalterado.
$USERprovavelmente será o nome de usuário do usuário atual; portanto, sua expressão provavelmente poderá ser substituída por apenas ~.
Como outras respostas apontaram, o comportamento depende de qual ordem o shell faz ~e as $expansões e se ele fará os dois pela mesma palavra.
O comportamento que você estava procurando é possível obter bashcom uma mudança muito pequena no seu comando. Basta prefixar o comando com eval.
eval "cd ~$USER"
mudará para o diretório inicial do usuário fornecido pelo nome de usuário na variável USER, desde $USERque não contenha caracteres especiais para o shell (se houver uma chance remota de que isso ocorra, você não deve passá-lo como argumento, evalpois isso seria perigoso ) ou /caracteres e que há uma entrada para esse usuário no banco de dados de usuários do sistema.
Uma maneira alternativa de procurar o diretório inicial de um usuário variável, se você estiver usando um dos shells em que a expansão til ocorre antes da expansão variável, é com getent . Esta ferramenta existe em pelo menos Linux, Solaris e FreeBSD; Não tenho certeza de quão universal é.
$ USER=bloggs
$ getent passwd "$USER" | cut -d: -f6
/home/b/bloggs
Assim como na expansão til, isso pode não dar a mesma coisa que su - $USER -c 'echo $HOME'seria impressa se você tivesse os privilégios para fazer isso.
perl -le 'print((getpwnam shift)[7])' -- "$USER"como potencialmente um pouco mais portátil.
Como o OP insiste em uma resposta, aqui está.
O comportamento desses comandos (e muitas outras coisas) depende do shell específico que você está usando. A menos que você especifique qual shell específico você usa, provavelmente não é possível dar uma resposta simples.
De fato, se você usar o tcsh, como eu, as duas expressões da pergunta do OP (como está escrito enquanto escrevo isso - não me responsabilizo por edições futuras!) Funcionam perfeitamente. Não sei o que outras conchas farão, já que não as uso. Então, talvez o OP não saiba tanto sobre o que pode ser feito quanto ele pensa :-)