¿Por qué no puedo cd a una tilde citada ('~')?

33

Escribo mi primer guión, así que estoy seguro de que esta es una pregunta básica, pero ¿alguien puede explicarme por qué puedo:

cd ~
cd bin
cd ~/bin
cd 'bin'

Pero no

cd '~'
cd '~/bin'

Necesito cduna ruta de directorio con un espacio en uno de los nombres de directorio, por lo que necesito las comillas (es Windows Program Filesen vino). Puedo evitarlo con dos cdcomandos, pero ¿por qué no puedo poner ~comillas?

Si escribo cd '~'(o cd "~") obtengo:

bash: cd: ~: No such file or directory
B. Tanner
fuente
29
Pregúntese esto: si no funcionara así, ¿cómo entraría cden un directorio llamado ~?
Jörg W Mittag
2
Como nota al margen, si está escribiendo un guión, debería usar rutas absolutas y evitarlas por cdcompleto. Use variables para almacenar nombres de ruta que no desea escribir varias veces, por ejemplopf=~/.wine/drive_c/Program\ Files/; cp /path/to/file "$pf"
postre
8
@jamesqf: ¿Por qué un sistema sensato presume saber mejor que yo lo que quiero nombrar a mis archivos y directorios? Además, nunca entendí por qué Unix optó por la señalización mágica en banda de separadores de componentes de ruta y terminadores de ruta. ¿Qué hay de malo con un archivo / directorio llamado /o NUL?
Jörg W Mittag
3
@ JörgWMittag presumiblementecd ./~
k_g
2
@jamesqf Solo para notar que históricamente, los sistemas de archivos de Unix permitían cualquier carácter en un nombre de archivo excepto '/' (separador de ruta) y '\ 0' (NUL - carácter de terminación de cadena) - como señala Jorg. No hay otras restricciones. Ha habido muchas implementaciones del sistema de archivos Unix, por lo que la introducción de restricciones en cualquiera de ellas habría roto la compatibilidad y aumentado la complejidad, ¡y se habría visto como "extraño"! Y la expansión '~' solo se introdujo relativamente recientemente en csh y, más ampliamente, en bash, los archivos / directorios con caracteres '~' no son desconocidos (por ejemplo, myfile ~ como respaldo para myfile).
SusanW

Respuestas:

79

Como @karel señaló en su respuesta, ~es un personaje especial y Bash lo expandió al directorio de inicio del usuario actual. Consulte el manual de Bash sobre "Expansión de Tilde" , o busque el título "Expansión de Tilde" en la página de manual ( man bash).

Cualquier tipo de cita alrededor del ~evita esta expansión de tilde.


Para responder a su pregunta sobre cómo aún puede usarlo cden un directorio con espacios en su nombre, hay algunas alternativas:

  • Omite comillas y escapa de los espacios con barras invertidas en su lugar:

    cd ~/foo/spaces\ are\ cool/bar
  • Cite el resto del camino, pero omítalos alrededor de la tilde y la primera barra:

    cd ~/"foo/spaces are cool/bar"

    Como puede ver, puede concatenar cadenas entre comillas y sin comillas en Bash simplemente escribiéndolas una al lado de la otra sin espacios en el medio.

  • Utilice la variable de entorno en $HOMElugar de la tilde, que aún se expande dentro de "comillas dobles" (pero no 'comillas simples'):

    cd "$HOME/foo/spaces are cool/bar"
Byte Commander
fuente
3
@rexkogitans ~'/...'no funcionará y no es lo que tiene esta respuesta. ~/'...'o ~/"..."funcionará.
hvd
tld; dr: porque esa es la sintaxis de shell
Sergiy Kolodyazhnyy
@hvd gracias. Error tipográfico fijo. Esta es la respuesta más completa y también explica cómo resolver lo que quiere hacer el OP. ~/'path'Es el camino a seguir.
rexkogitans
1
@hvd solo un poco de curiosidad, ¿por qué no ~'/...'funcionaría? La barra diagonal no es un carácter especial, por lo que parece que debería funcionar dentro o fuera de las comillas.
Kodos Johnson
66
@KodosJohnson Echa un vistazo a la sección de la página de manual de Bash sobre "Expansión de Tilde". El párrafo relevante de eso también se cita en la respuesta de postre a continuación. TL; DR: la expansión de Tilde se lleva a cabo si el primer carácter de una palabra es una tilde sin comillas, entonces todo lo que se encuentre entre esa tilde y la siguiente barra sin comillas se considera el "prefijo de tilde". Si este prefijo no es válido como +, -, un número o un nombre de usuario (tampoco se permiten las comillas), la expansión falla y se obtiene un carácter literal ~.
Byte Commander
17

~ es un carácter especial que el shell interpreta como el directorio de inicio del usuario conectado. '~' es interpretado por el shell como un carácter literal ~, no como el directorio de inicio del usuario conectado porque al encerrar una cadena dentro de dos caracteres de comillas simples se interpreta esa cadena como una cadena de texto literal.

karel
fuente
~no es un alias en el sentido en que lo bashinterpreta: los alias permiten que una cadena sea sustituida por una palabra cuando se usa como la primera palabra de un comando simple. . Como explico en mi respuesta a continuación, es más bien una expansión.
postre
15

Esta es una bashcaracterística llamada Tilde Expansion . Citando man bash:

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 shell HOME. Si HOME no está configurado, el directorio de inicio del usuario que ejecuta el shell se sustituye en su lugar.

Para que la expansión funcione, el carácter tilde ~debe estar sin comillas, de lo contrario, el carácter se toma literalmente y cdfalla si no hay un directorio nombrado ~presente en el directorio actual. Vea esta respuesta entretenida para obtener una explicación de la cita bash. Si necesita citar parte de la ruta, puede:

  1. cite al menos los caracteres que necesitan comillas con comillas simples, p. ej.

    ~/dir' 'with' 'spaces/

    o

    ~/'dir with spaces/'
  2. cite al menos los caracteres que necesitan comillas con comillas dobles, p. ej.

    ~/dir" "with" "spaces/

    o

    ~/"dir with spaces/"
  3. cite solo los caracteres que necesitan comillas con barras invertidas, p. ej.

    ~/dir\ with\ spaces/

Tilde Expansion tiene algunas características más interesantes, por ejemplo:

  • ~+se expande al valor de PWD, es decir, el directorio de trabajo actual
  • ~-se expande al valor de OLDPWD, es decir, el directorio de trabajo anterior
  • ~john se expande al directorio de inicio asociado con el nombre de inicio de sesión "john"
postre
fuente
Por cierto, también está bien 'sobrecitar' con barras invertidas; por ejemplo, $ touch a; cd \a. (Pensé que esto podría tener problemas con el cd \n, pero la experimentación, al menos en mi versión del bashsugiere que trabaja muy bien.)
LSpice
1

Explore usando el echocomando

La forma más fácil de explorar cómo funcionan las cosas en bash es con el echocomando. En el caso de ~usar esto:

$ echo ~
/home/rick
$ echo '~'
~
$ echo "~"
~
$ echo `~`
bash: /home/rick: Is a directory

Como puede ver, cuando una comilla simple o una comilla doble ~se interpreta literalmente como una cadena y no se expande como una variable. Cuando usa backticks (`) se ejecuta como un comando y genera un mensaje de error.

WinEunuuchs2Unix
fuente