~
nas cotações permanece literal ~
. A parte relevante do Manual de Referência de Bash começa com
If a word begins with an unquoted tilde character (
~
), …
Para ver a diferença, compare:
file="~/.gitconfig"
echo "$file"
file=~/".gitconfig"
echo "$file"
No seu primeiro exemplo, $(…)
funciona primeiro e, no contexto, ~
não é citado. Então, ele se expande conforme o esperado.
Seu $file
, quando "não funciona", contém literal ~
. O padrão POSIX diz :
The order of word expansion shall be as follows:
Tilde expansion […], parameter expansion […], command substitution […], and arithmetic expansion […] shall be performed, beginning to end. […]
Como a expansão do til é executada antes da expansão do parâmetro, uma variável que se expande para ~/something
não se expande ainda mais para um caminho adequado.
Lembre-se de que ~
ou ~/
é especial para o seu shell em algumas circunstâncias, mas para (quase?) qualquer outra ferramenta, não é um caminho válido. Quando funciona, é porque o shell faz sua "mágica" primeiro e a outra ferramenta vê o caminho já expandido (como /Users/jord
).
Note em seu último exemplo que a expansão de til não funciona , você ainda recebe o literal ~
e é muito tarde para o shell fazer algo a respeito sem truques adicionais (como eval
). dirname
não reclama porque trabalha com strings. Não importa se o caminho fornecido é válido, existente, etc. Ele basicamente procura apenas o último componente não-barra e descarta-o com barras finais (se houver).
Veja também esta resposta .