¿Por qué tilde (~) no se expande cuando se usa con el argumento CLI que comienza con el guión?

9

Perdí un par de horas tratando de ejecutar el servidor VNC (x0vncserver) y el cliente se negó a conectarse con un mensaje extraño que

No password configured for VNC Auth

El servidor también imprime este error.

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

Ok, perdí mucho tiempo hasta que me di cuenta de que la tilde no estaba expandida por el shell ni por x0vncserver. Entonces corrí estas pruebas

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

Pero

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

¿Porqué es eso? ¿Por qué el shell se niega a expandir tilde si el argumento comienza con un guión? Pensé que tilde siempre se expandirá siempre que no se cite, pero aparentemente hay otra regla que entra en juego.

Tihomir Mitkov
fuente
Relacionado: Expansión de tilde en zsh
Stéphane Chazelas
Ver también: ¿~ siempre es igual a $ HOME
Stéphane Chazelas

Respuestas:

13

Esta es una peculiaridad del bashshell descrito en su manual:

Bash también realiza una expansión de tilde en palabras que satisfacen las condiciones de asignaciones variables (como se describe anteriormente en PARÁMETROS) cuando aparecen como argumentos para comandos simples. Bash no hace esto, excepto por los comandos de declaración enumerados anteriormente, cuando está en modo posix.

Esto significa que bash va a expandir la tilde en su PasswordFile=~/.vnc/passwdcadena, ya que es un argumento para echoque se parece a una asignación de variables.

La cadena --PasswordFile=~/.vnc/passwdno parece una asignación de variable ya que la cadena --PasswordFileno es un nombre de variable válido.

Tenga en cuenta que bashno hace esto cuando se ejecuta en modo POSIX, y que otros shells, como zsh, ksho yashno lo hacen de forma predeterminada ( zshtiene una magicequalsubstopción para que la expansión de tilde se realice después de signos iguales sin comillas ( =)).

Si desea asegurarse de que la ruta del directorio inicial del usuario actual se expanda correctamente como parte de un argumento a un comando, use el $HOMEvalor en lugar de la tilde:

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

Los "comandos de declaración antes mencionados" se hace referencia en el manual son construidos en los comandos alias, declare, typeset, export, readonly, y local.

Kusalananda
fuente
1
+1 | No pensaría en eso.
LinuxSecurityFreak
Aunque nota: bash --posix -c '"export" a=~; printf "%s\n" "$a"'salidas ~.
Stéphane Chazelas
2
Tenga en cuenta que la ~expansión en alias a=~sería un error de conformidad POSIX (y no es útil). Pero así es como lo hizo ksh88 (eso cambió en ksh93) y es probablemente por qué bash, zsh y pdksh también lo hacen. Por qué lo yashque se escribió en contra de la especificación POSIX no lo hace.
Stéphane Chazelas
Esta es la respuesta correcta, pero el enfoque correcto hubiera sido simplemente proporcionar el argumento de la opción como un argumento separado, en lugar de fusionarse con la opción usando =un argumento. Entonces la expansión de tilde está al comienzo de una palabra y la pregunta es discutible.
JdeBP
1
@JdeBP, como sucede, en el caso de x0vncserver, x0vncserver --PasswordFile fileno funciona, necesita --PasswordFile=file.
Stéphane Chazelas