Digamos que quiero almacenar el siguiente comando en una variable
cd "/cygdrive/c/Program Files/"
Entonces hago esto
dir="cd \"/cygdrive/c/Program Files/\""
Eso debería almacenar el comando para navegar al directorio Archivos de programa, por lo que cuando escribo $ dir me lleva a ese directorio. Para verificar que las citas se hayan escapado correctamente, escribo
echo $dir
lo que me da
cd "/cygdrive/c/Program Files/"
Entonces todo debería estar funcionando bien. Sin embargo, cuando escribo,
$dir
yo obtengo
bash: cd: "/cygdrive/c/Program: No such file or directory
¿Qué estoy haciendo mal? Estoy usando Cygwin, pero supongo que este problema se aplica a bash en general.
Respuestas:
Respuesta corta: vea BashFAQ # 050 ("Estoy tratando de poner un comando en una variable, ¡pero los casos complejos siempre fallan!").
Respuesta larga: cuando bash analiza un comando, analiza las comillas antes de reemplazar las variables; nunca retrocede y analiza las comillas en los valores de las variables, por lo que terminan sin hacer nada útil. Usar echo para verificar el comando es completamente engañoso porque muestra el comando después de analizarlo; si desea ver lo que realmente se está ejecutando, use
set -x
los comandos de impresión de shell a medida que se ejecutan, o use enprintf "%q " $dir; echo
lugar de echo simple.Si desea almacenar un comando complejo (es decir, uno con espacios u otros caracteres especiales en las "palabras"), debe colocarlo en una matriz en lugar de una variable de texto simple y luego expandirlo con el idioma `" $ { matriz [@]} ", así:
Ahora, si el propósito es hacer una taquigrafía fácil de escribir, claramente este no es el camino a seguir. Use un alias o función de shell en su lugar:
o
fuente
Cuando bash se expande
$dir
, solo divide palabras y se pega. La división de palabras produce tres palabras:cd
,"/cygdrive/c/Program
yFiles/"
. Entonces el comando a ejecutar escd
con dos argumentos;cd
solo mira su primer argumento"/cygdrive/c/Program
, que no es un directorio existente.Si desea realizar una evaluación completa del shell en el contenido de una variable, use
eval
:Tenga en cuenta que necesita las comillas dobles
$dir
, de lo contrario, primero se realizaría la división de palabras, luegoeval
concatenaría sus argumentos con espacios. Esto funcionaría aquí, pero en general iría mal (por ejemplo, si hubiera dos espacios consecutivos en un nombre de archivo).Sin embargo, una cadena no es la forma correcta de almacenar un comando de shell que desea ejecutar. A menos que tenga un requisito inusual, debería usar una función en su lugar:
Si usted está realmente interesado en la tipificación
$dir
de cambiar a un directorio en particular y esto no es sólo un ejemplo sencillo, puesto fiesta de 4, ponershopt -s autocd
en su.bashrc
y conjuntodespués de lo cual puede escribir solo
"/cygdrive/c/Program Files/"
o"$dir"
en el símbolo del sistema para cambiar a ese directorio. Todavía necesitas las comillas dobles$dir
; si no te gusta, usa zsh en lugar de bash.fuente
Almacenar comandos en variables generalmente no es una buena idea. Para eso están las funciones y los alias.
Más bien que
prueba uno de estos:
o
o
La primera forma, almacenar el nombre del directorio en una variable, significa escribir un poco más, pero es más claro cuando ejecuta el comando que está haciendo a
cd
. El segundo es más cercano a lo que estás tratando de lograr. (No uso mucho los alias en bash; en realidad no estoy seguro de qué ventaja tienen sobre las funciones).EDITAR:
Y
dir
probablemente sea un mal nombre para un alias o función, ya que existe un comando con ese nombre (es básicamente una versión dels
, al menos si tiene coreutils de GNU).fuente
Storing commands in variables is generally not a good idea. That's what functions and aliases are for.
Tratar
Pero aún más específicamente:
/programming/4334467/cygwin-using-a-path-variable-containing-a-windows-path-with-a-space-in-it
fuente