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...).
bashespecificamente (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 $varseja 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, kshmas não bashdesde a versão 4.0).
case ~ in ~) ...
${var#~} (embora não em outras conchas)
cmd foo=~(embora não quando invocado como she apenas quando o que está à esquerda da =figura tiver o formato de um bashnome de variável não citado )
cmd ~/x (exigido pelo POSIX obviamente)
cmd ~:x(mas não x:~:xou 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 ~use 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 --prefixnã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 HOMEvariá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 bashversõ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 $HOMEcomeç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 $HOMElike -, +2...) ou simplesmente:
cd
(o cdleva 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ê cdpara antes).
- diretórios nomeados dinâmicos . Você pode definir seu próprio mecanismo para decidir como
~somethingestá sendo expandido.
~que será equivalente a$HOMEqualquer ambiente POSIX; mas eu posso estar errado.