Por que til (~) não se expande quando usado com o argumento CLI começando com dash?

9

Perdi algumas horas tentando executar o servidor VNC (x0vncserver) e o cliente se recusou a se conectar com uma mensagem estranha que

No password configured for VNC Auth

O servidor também imprime este erro

 SVncAuth:    opening password file '~/.vnc/passwd' failed

Ok, perdi muito tempo até perceber que o til não era expandido pelo shell nem pelo x0vncserver. Então eu fiz esses testes

$ echo --PasswordFile=~/.vnc/passwd
--PasswordFile=~/.vnc/passwd

Mas

$ echo PasswordFile=~/.vnc/passwd
PasswordFile=/home/tichomir/.vnc/passwd

Por que é que? Por que o shell se recusa a expandir o til se o argumento começa com um traço? Eu pensei que til sempre se expandirá, desde que não seja citado, mas aparentemente há outra regra que entra em jogo?

Tihomir Mitkov
fonte
Related: Expansão do til no zsh
Stéphane Chazelas 03/02/19
Veja também: ~ sempre é igual a $ HOME
Stéphane Chazelas 03/02/19

Respostas:

13

Essa é uma peculiaridade do bashshell descrito em seu manual:

O Bash também realiza expansão de til em palavras que satisfazem as condições de atribuições de variáveis ​​(como descrito acima em PARÂMETROS) quando elas aparecem como argumentos para comandos simples. O Bash não faz isso, exceto pelos comandos de declaração listados acima, quando no modo posix.

Isto significa que bash irá expandir o til em sua PasswordFile=~/.vnc/passwdcorda, uma vez que é um argumento para echoque se parece com uma atribuição de variável.

A sequência --PasswordFile=~/.vnc/passwdnão se parece com uma atribuição de variável, pois --PasswordFilenão é um nome de variável válido.

Note-se que bashnão faz isso quando executado no modo POSIX, e que outras conchas, como zsh, kshou yashnão fazem isso por padrão ( zshtem uma magicequalsubstopção para a expansão til a ser realizada após sinais de igual não cotados ( =) embora).

Se você deseja garantir que o caminho do diretório inicial do usuário atual seja expandido corretamente como parte de um argumento para um comando, use o $HOMEvalor em vez do til:

echo --PasswordFile="$HOME/.vnc/passwd"

Os "comandos de declaração listados acima" referida no manual são o construído em comandos alias, declare, typeset, export, readonly, e local.

Kusalananda
fonte
1
+1 | Eu não pensaria nisso.
LinuxSecurityFreak
Embora nota: bash --posix -c '"export" a=~; printf "%s\n" "$a"'saídas ~.
Stéphane Chazelas
2
Observe que a ~expansão alias a=~seria um erro de conformidade do POSIX (e não é útil). Mas foi assim que o ksh88 fez (que mudou no ksh93) e provavelmente é por isso que o bash, o zsh e o pdksh também o fazem. Por yashque o que foi escrito contra a especificação POSIX não faz isso?
Stéphane Chazelas
Esta é a resposta certa, mas a abordagem correta seria fornecer apenas o argumento da opção como um argumento separado, em vez de mesclar com a opção usando =um argumento. Então a expansão do til está no início de uma palavra e a questão é discutível.
JdeBP
1
@JdeBP, por acaso, no caso de x0vncserver, x0vncserver --PasswordFile filenão funciona, você precisa --PasswordFile=file.
Stéphane Chazelas