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 -xlos comandos de impresión de shell a medida que se ejecutan, o use enprintf "%q " $dir; echolugar 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/ProgramyFiles/". Entonces el comando a ejecutar escdcon dos argumentos;cdsolo 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, luegoevalconcatenarí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
$dirde cambiar a un directorio en particular y esto no es sólo un ejemplo sencillo, puesto fiesta de 4, ponershopt -s autocden su.bashrcy 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
dirprobablemente 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