Fazer cd
é basicamente chamar cd
sem argumentos e de acordo com o comportamento cd
"... se dir não for fornecido, o valor da variável de shell HOME é o padrão." (de manual do bash ). Por contraste, cd ~
é quando você fornece argumentos para o comando cd
, que por acaso é ~
e o shell executará expansão do til . Tanto quanto voltar ao diretório home do usuário - não há diferença. Em qualquer um dos casos, a variável de ambiente HOME
será consultada:
$ env 'HOME=/usr' bash -c 'cd;pwd; cd ~;pwd'
/usr
/usr
Efetivamente, isso também não tem diferença em relação a cd $HOME
. No entanto, enquanto cd
fará uma única ação, o til poderá ser usado para executar outras expansões como ~+
para o diretório de trabalho atual.
No entanto, curiosamente, podemos unset HOME
para quebrar cd
, mas ~
ainda funcionará:
$ bash -c 'cd /usr;unset HOME;cd;pwd;cd ~;pwd'
bash: line 0: cd: HOME not set
/usr
/home/xieerqi
Por quê? Novamente, responda no manual:
If HOME is unset, the home directory of the user executing the shell is substituted instead. Otherwise, the tilde-prefix is replaced with the home directory associated with the specified login name.
Observe que a desativação é diferente de fazer a variável vazia HOME=
e tem efeito. A documentação fala especificamente sobre a variável não definida. Tornar variável igual a string vazia tem efeito oposto ao que esperávamos:
bash-4.3$ env 'HOME=' bash -c 'cd /usr;set|grep "^HOME"; stat -c "%F" ~;cd;pwd'
HOME=
stat: cannot stat '': No such file or directory
/usr
Aqui você pode ver que fazer HOME
empty string quebra o comportamento til e cd
.
Tilde e $HOME
têm uma diferença e uma razão diferente para a existência. $HOME
é uma variável de shell, que também coincidentemente é uma das variáveis de ambiente - e que está disponível para todos os programas; em C você usaria environ()
para acessar isso. Por contraste, tilde
é a sintaxe específica do shell que executa a expansão do til, embora você possa usar a função wordexp()
para executar uma expansão semelhante à shell ( referência ) em C também.
O motivo pelo qual ~
representa HOME
foi respondido em esta pergunta : uma vez o caractere til compartilhou a mesma tecla com HOME
no terminal Lear-Siegler ADM-3A. HOME
, ao contrário, é uma variável de ambiente que tinha um significado puramente simbólico e nenhuma representação física.
Além disso, o fato de HOME
ser uma variável de ambiente nos permite desabilitá-la, já que não podemos definir ~
para outra coisa por meios simples.
# cd ~ will still work, because ~ is blank, so it's same as just cd
$ bash -c 'unset HOME; echo $HOME; cd ~;pwd'
/home/xieerqi
$ env 'HOME=' bash -c 'echo $HOME; cd ~;pwd'
/home/xieerqi
Observe a linha em branco em que o primeiro echo
produz a variável não definida, e o fato disso. Por outro lado, não podemos fazer coisas assim para til:
$ bash -c '~=; cd ~;pwd'
bash: ~=: command not found
/home/xieerqi
$ bash -c '~=$'$ env 'HOME=' bash -c 'echo $HOME; stat ~;'
stat: cannot stat '': No such file or directory
'; cd ~;pwd'
bash: ~=bash: command not found
/home/xieerqi
$ bash -c 'unset ~; cd ~;pwd'
bash: line 0: unset: '/home/xieerqi': not a valid identifier
/home/xieerqi
No entanto, a alteração de HOME
afeta ~
:
$ bash -c 'cd /etc/;stat -c "%n" ~+'
/etc
Além disso, como ~
também funciona como um caractere de expansão, podemos fazer coisas assim para mostrar o diretório de trabalho atual:
$ bash -c 'cd /etc/;PWD="/usr";stat -c "%n" ~+'
/usr
Considerando que, se quisermos fazer isso por meio de variáveis de ambiente, precisamos de PWD
, e HOME
permanecerá o mesmo, ou se você fizer coisas como echo $HOME+
- isso é apenas concatenação de strings / variáveis. Mas, novamente, ~+
tira informações de variáveis de ambiente:
$ env 'HOME=/usr' bash -c 'cd;pwd; cd ~;pwd'
/usr
/usr
OBSERVAÇÃO : as expansões ~+
e ~-
funcionam em ksh
, mas não em dash
.
Para responder a algumas das suas perguntas específicas:
Is it something specific to BASH or would they behave differently in another Shell?
Não, isso deve ser um comportamento consistente. ksh
, dash
e csh
- todos se comportam com cd
ou cd ~
.
why was the ~ added in the first place then ?
Eu diria conveniência e razões históricas como explicado na resposta vinculada sobre o til. Eventualmente, cresceu para executar mais do que apenas expansão de diretório inicial.