¿Por qué falla mkdir (no existe tal archivo o directorio) en un script con BIN_DIR = “~ / bin /”?

Respuestas:

11

El mensaje de error se produce porque ~se cita la tilde , como se describe en la respuesta de Zanna . Si desea utilizar ~, la parte relevante del script debe ser:

BIN_DIR=~/bin/

Si por alguna razón desea citar la cadena, puede usar la variable de entorno $HOME:

BIN_DIR="$HOME/bin/"

En mi opinión, el segundo enfoque es una mejor práctica.

pa4080
fuente
66
No hay nada de malo en usar ~scripts. Funciona exactamente de la misma manera que en la línea de comandos. El problema es que los bloques de citas tienden a expandirse como se explica en la respuesta de Zanna .
terdon
@terdon, estoy de acuerdo. Pero no he dicho que haya algo mal, pero es una mejor idea, porque debes prestar menos atención.
pa4080
55
Pero no hay absolutamente ninguna diferencia entre la línea de comando y un script aquí. El hecho de que esto esté en un script es completamente irrelevante, tendría exactamente el mismo error en la línea de comandos. El problema es la cita, no es que esté en un script.
terdon
Si bien eso es totalmente cierto, también es cierto que usar $HOMEscripts es una buena idea.
postre
3
@ pa4080 ¿Puede agregar una explicación de por qué cree que es mejor expandir $HOMEque usar la expansión tilde? La única explicación que ha dado es decir, "es una mejor idea, porque debería prestar menos atención". No tengo idea de lo que eso significa. ¿Puedes exponerlo en una edición? Sin ella, no hay nada que respalde su respuesta, por lo que seguramente pertenece a ella. POSIX ha requerido la expansión de Tilde desde hace bastante tiempo y la línea hashbang del script es #!/bin/bashasí que supongo que la portabilidad no es la razón.
Eliah Kagan
23

No funciona porque ~se cita. Las comillas dobles " suprimen la expansión de tilde . No hay directorio con el nombre literal ~/bin. Como se explica en man bash(énfasis mío):

Expansión Tilde

Si una palabra comienza con un carácter de tilde sin comillas (`~ '), todos los caracteres que preceden a la primera barra sin comillas (o todos los caracteres, si no hay una barra sin comillas) se consideran prefijos de tilde. Si ninguno de los caracteres en el prefijo tilde se cita, los caracteres en el prefijo tilde después de la tilde se tratan como un posible nombre de inicio de sesión. Si este nombre de inicio de sesión es la cadena nula, la tilde se reemplaza con el valor del parámetro de inicio HOME. Si HOME no está configurado, el directorio de inicio del usuario que ejecuta el shell se sustituye en su lugar. De lo contrario, el prefijo tilde se reemplaza con el directorio de inicio asociado con el nombre de inicio de sesión especificado.

Puede eliminar las comillas , ya que ~es el único carácter en la ruta ~/binque hará que el shell realice una expansión, y queremos la expansión en este caso. La cáscara no realizará ningún expansiones adicionales en el resultado de la expansión tilde, al menos en Bash 4 , que todas las versiones actuales o remotamente recientes de Ubuntu tienen . Entonces, incluso si su directorio de inicio contiene caracteres inusuales como espacios, está bien.

O puede usar en $HOMElugar de ~, porque la expansión de parámetros no se suprime con comillas dobles, solo con comillas simples . Las comillas dobles no garantizan que el valor expandido en sí no es objeto de ningún expansiones adicionales, por lo que la división de palabras o la expansión de nombre de archivo no ocurrirán. También $HOMEfunciona incluso con directorios de inicio con nombres extraños, siempre que mantenga las comillas dobles.

Zanna
fuente
Según esta declaración, "la expansión de parámetros no se suprime mediante comillas dobles, solo entre comillas simples" : la salida de cd '~'es -bash: cd: ~: No such file or directory.
pa4080
2
@ pa4080 La expansión de ~no es parte de la expansión de parámetros.
Barmar