O que é importante entender é que a ~
expansão é um recurso do shell (de alguns shells), não é um personagem mágico do que significa o diretório inicial onde quer que seja usado.
Ele é expandido (pelo shell, que é um aplicativo usado para interpretar linhas de comando), como $var
é expandido para seu valor sob algumas condições, quando usado em uma linha de comando do shell antes que o comando seja executado.
Esse recurso apareceu pela primeira vez no shell C no final da década de 1970 (o shell Bourne não o possuía, nem seu antecessor, o shell Thompson), mais tarde foi adicionado ao shell Korn (um shell mais novo construído sobre o shell Bourne no anos 80). Ele acabou sendo padronizado pelo POSIX e agora está disponível na maioria dos shells, incluindo os que não são do POSIX fish
.
Como ele é amplamente utilizado em shells, alguns aplicativos não-shell também o reconhecem como significando o diretório inicial. Esse é o caso de muitas aplicações em seus arquivos de configuração ou a sua própria linha de comando ( mutt
, slrn
, vim
...).
bash
especificamente (que é o shell do projeto GNU e amplamente usado em muitos sistemas operacionais baseados em Linux), quando chamado sh
, segue principalmente as regras do POSIX sobre ~
expansão, e em áreas não especificadas pelo POSIX, se comporta principalmente como o shell Korn (de que é um clone parcial).
Embora $var
seja expandido na maioria dos lugares (exceto dentro de aspas simples), a ~
expansão, sendo uma reflexão tardia, é expandida apenas em algumas condições específicas.
Ele é expandido quando por seu próprio argumento em contextos de lista, em contextos em que uma sequência é esperada.
Aqui estão alguns exemplos de onde é expandida bash
:
cmd arg ~ other arg
var=~
var=x:~:x
(exigido pelo POSIX, usado para variáveis como PATH
, MANPATH
...)
for i in ~
[[ ~ = text ]]
[[ text = ~ ]]
(a expansão de ~
ser tomada como padrão na AT&T, ksh
mas não bash
desde a versão 4.0).
case ~ in ~) ...
${var#~}
(embora não em outras conchas)
cmd foo=~
(embora não quando invocado como sh
e apenas quando o que está à esquerda da =
figura tiver o formato de um bash
nome de variável não citado )
cmd ~/x
(exigido pelo POSIX obviamente)
cmd ~:x
(mas não x:~:x
ou x-~-x
)
a[~]=foo; echo "${a[~]} $((a[~]))"
(não em outras conchas)
Aqui estão alguns exemplos em que não é expandido:
echo "~" '~'
echo ~@ ~~
(observe também que ~u
se destina a expandir para o diretório inicial do usuário u
).
echo @~
(( HOME == ~ ))
, $(( var + ~ ))
- com
extglob
: case $var in @(~|other))...
(embora case $var in ~|other)
esteja OK).
./configure --prefix=~
(como --prefix
não é um nome de variável válido)
cmd "foo"=~
(em bash
, por causa das aspas).
- quando invocado como
sh
: export "foo"=~
, env JAVA_HOME=~ cmd
...
Quanto ao que ele se expande: ~
expande sozinho para o conteúdo da HOME
variável, ou quando não está definido, para o diretório inicial do usuário atual no banco de dados da conta (como uma extensão, pois o POSIX deixa esse comportamento indefinido).
Deve-se notar que no ksh88 e nas bash
versões anteriores à 4.0, a expansão do til passou por globbing (geração de nome de arquivo) em contextos de lista:
$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~
Isso não deve ser um problema em casos habituais.
Observe que, por ser expandido, o mesmo aviso se aplica a outras formas de expansão.
cd ~
Não funciona se $HOME
começa com -
ou contém ..
componentes. Portanto, mesmo que seja pouco provável que faça alguma diferença, estritamente falando, deve-se escrever:
cd -P -- ~
Ou até:
case ~ in
(/*) cd -P ~;;
(*) d=~; cd -P "./$d";;
esac
(para cobrir valores de $HOME
like -
, +2
...) ou simplesmente:
cd
(o cd
leva ao seu diretório pessoal sem nenhum argumento)
Outras conchas têm ~
expansões mais avançadas . Por exemplo, em zsh
, temos:
~4
, ~-
, ~-2
(Com conclusão) usado para expandir os diretórios em sua pilha de diretórios (os lugares que você cd
para antes).
- diretórios nomeados dinâmicos . Você pode definir seu próprio mecanismo para decidir como
~something
está sendo expandido.
~
que será equivalente a$HOME
qualquer ambiente POSIX; mas eu posso estar errado.