Lo que es importante entender es que la ~
expansión es una característica del shell (de algunos shells), no es un personaje mágico que significa su directorio de inicio donde sea que se use.
Se expande (mediante el shell, que es una aplicación utilizada para interpretar líneas de comando), al igual que $var
se expande a su valor en algunas condiciones cuando se usa en una línea de comando del shell antes de ejecutar el comando.
Esa característica apareció por primera vez en el C-shell a fines de la década de 1970 (el shell Bourne no lo tenía, ni su predecesor, el shell Thompson), luego se agregó al shell Korn (un shell más nuevo construido sobre el shell Bourne en el 80s). Eventualmente fue estandarizado por POSIX y ahora está disponible en la mayoría de los shells, incluidos los que no son POSIX fish
.
Debido a su uso tan extendido en shells, algunas aplicaciones que no son de shell también lo reconocen como el directorio de inicio. Ese es el caso de muchas aplicaciones en sus archivos de configuración o de su propia línea de comandos ( mutt
, slrn
, vim
...).
bash
específicamente (que es el shell del proyecto GNU y ampliamente utilizado en muchos sistemas operativos basados en Linux), cuando se invoca como sh
, en su mayoría sigue las reglas POSIX sobre ~
expansión, y en áreas no especificadas por POSIX, se comporta principalmente como el shell Korn (de que es un clon parcial).
Si bien $var
se expande en la mayoría de los lugares (excepto dentro de comillas simples), la ~
expansión, una idea de último momento solo se expande en unas pocas condiciones específicas.
Se expande cuando está en su propio argumento en contextos de lista, en contextos donde se espera una cadena.
Aquí hay algunos ejemplos de dónde se expande bash
:
cmd arg ~ other arg
var=~
var=x:~:x
(requerido por POSIX, usado para variables como PATH
, MANPATH
...)
for i in ~
[[ ~ = text ]]
[[ text = ~ ]]
(la expansión de ~
ser tomado como un patrón en AT&T ksh
pero no bash
desde 4.0).
case ~ in ~) ...
${var#~}
(aunque no en otras conchas)
cmd foo=~
(aunque no cuando se invoca como sh
, y solo cuando lo que está a la izquierda =
tiene la forma de un bash
nombre de variable sin comillas )
cmd ~/x
(requerido por POSIX obviamente)
cmd ~:x
(pero no x:~:x
o x-~-x
)
a[~]=foo; echo "${a[~]} $((a[~]))"
(no en otras conchas)
Aquí hay algunos ejemplos donde no se expande:
echo "~" '~'
echo ~@ ~~
(también tenga en cuenta que ~u
está destinado a expandirse al directorio de inicio del usuario u
).
echo @~
(( HOME == ~ ))
, $(( var + ~ ))
- con
extglob
: case $var in @(~|other))...
(aunque case $var in ~|other)
está bien).
./configure --prefix=~
(como --prefix
no es un nombre de variable válido)
cmd "foo"=~
(en bash
, debido a las comillas).
- Cuando se invoca como
sh
: export "foo"=~
, env JAVA_HOME=~ cmd
...
En cuanto a lo que se expande: ~
solo se expande al contenido de la HOME
variable, o cuando no está configurado, al directorio de inicio del usuario actual en la base de datos de la cuenta (como una extensión ya que POSIX deja ese comportamiento indefinido).
Cabe señalar que en ksh88 y bash
versiones anteriores a la 4.0, la expansión de tilde experimentó un bloqueo (generación de nombre de archivo) en contextos de lista:
$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~
Eso no debería ser un problema en los casos habituales.
Tenga en cuenta que debido a que está expandido, se aplica la misma advertencia que otras formas de expansión.
cd ~
No funciona si $HOME
comienza con -
o contiene ..
componentes. Entonces, aunque es muy poco probable que alguna vez haga alguna diferencia, estrictamente hablando, uno debería escribir:
cd -P -- ~
O incluso:
case ~ in
(/*) cd -P ~;;
(*) d=~; cd -P "./$d";;
esac
(para cubrir valores de me $HOME
gusta -
, +2
...) o simplemente:
cd
(como lo cd
lleva a su directorio de inicio sin ningún argumento)
Otros proyectiles tienen ~
expansiones más avanzadas . Por ejemplo, en zsh
, tenemos:
~4
, ~-
, ~-2
(Con la terminación) que se utiliza para expandir los directorios en su pila de directorios (los lugares que ha cd
de antes).
- directorios con nombre dinámico . Puede definir su propio mecanismo para decidir cómo
~something
se está expandiendo.
~
que será equivalente a$HOME
cualquier entorno POSIX; Pero podría estar equivocado.