O que é importante entender é que ~
expansion é um recurso do shell (de alguns shells), não é um magic character que significa seu diretório home 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 do comando ser executado.
Esse recurso apareceu pela primeira vez no C-shell no final dos anos 1970 (o shell Bourne não o tinha, nem seu antecessor, o shell Thompson), foi posteriormente adicionado ao shell Korn (um shell mais novo construído sobre o Bourne shell nos anos 80). Ele acabou sendo padronizado pelo POSIX e agora está disponível na maioria dos shells, incluindo os que não são POSIX, como fish
.
Como ele é amplamente usado em shells, alguns aplicativos que não são shell também o reconhecem como significando o diretório inicial. Esse é o caso de muitos aplicativos em seus arquivos de configuração ou na linha de comando própria ( mutt
, slrn
, vim
...).
bash
especificamente (que é o shell do projeto GNU e amplamente usado em muitos sistemas operacionais baseados em Linux), quando invocado como sh
, segue principalmente o Regras POSIX sobre a expansão ~
e, em áreas não especificadas pelo POSIX, se comportam principalmente como o shell Korn (do qual é parte o clone ), embora veja o bug mencionado abaixo.
Enquanto $var
é expandido na maioria dos locais (exceto entre aspas simples), ~
expansão, sendo uma reflexão tardia é expandida apenas em algumas condições específicas.
Ele é expandido quando em seu próprio argumento em contextos de lista, em contextos em que uma string é esperada.
Aqui estão alguns exemplos de onde ele foi expandido em bash
:
-
cmd arg ~ other arg
-
var=~
-
var=x:~:x
(requerido pelo POSIX, usado para variáveis comoPATH
,MANPATH
...) -
for i in ~
-
[[ ~ = text ]]
-
[[ text = ~ ]]
(~
sendo considerado como padrão emksh
, mas nãobash
). -
case ~ in ~) ...
-
${var#~}
(embora não em algumas outras shells) -
cmd foo=~
(embora não quando invocado comosh
, e somente quando o que está à esquerda do=
tenha o formato de um nome de variávelbash
sem aspas) -
cmd ~/x
(requerido pelo POSIX obviamente) -
cmd ~:x
(mas nãox:~:x
oux-~-x
) -
a[~]=foo; echo "${a[~]} $((a[~]))"
(não em algumas outras shells)
Aqui estão alguns exemplos em que não estão expandidos:
-
echo "~" '~'
-
echo ~@ ~~
(observe também que~u
se destina a expandir para o diretório inicial do usuáriou
). -
echo @~
-
(( HOME == ~ ))
,$(( var + ~ ))
- com
extglob
:case $var in @(~|other))...
(emboracase $var in ~|other)
esteja OK). -
./configure --prefix=~
(como--prefix
não é um nome de variável válido) -
cmd "foo"=~
(embash
, por causa das aspas). - quando chamado como
sh
:export "foo"=~
,env JAVA_HOME=~ cmd
...
Quanto ao que é expandido para: ~
sozinho se expande para o conteúdo da variável HOME
, 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 desde POSIX deixa esse comportamento indefinido).
Deve-se observar que em bash
versões anteriores à 4.0, a expansão de til foi submetida a 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 comuns.
Observe que, como ele é expandido, o mesmo aviso se aplica a outras formas de expansão.
cd ~
Não funciona se $HOME
começar com -
ou contiver ..
componentes. Então, mesmo que seja improvável que faça alguma diferença, estritamente falando, deve-se escrever:
cd -P -- ~
Ou até mesmo:
case ~ in
(/*) cd -P ~;;
(*) d=~; cd -P "./$d";;
esac
(para cobrir valores de $HOME
como -
, +2
...) ou simplesmente:
cd
(como cd
leva você ao seu diretório pessoal sem nenhum argumento)
Outras camadas têm expansões ~
mais avançadas. Por exemplo, em zsh
, temos:
-
~4
,~-
,~-2
(com conclusão) usado para expandir os diretórios na sua pilha de diretórios (os lugares com os quais você temcd
). -
diretórios nomeados dinâmicos . Você pode definir seu próprio mecanismo para decidir como o
~something
está sendo expandido.