Bash cita sin escapar en la sustitución de comandos

¿Puede alguien explicarme por qué esto está funcionando (enumerando el contenido de un directorio que tiene un espacio en blanco en su nombre):

ret="$(ls "my dir")" 

¿No debería ser interpretado como:

 ret="$(ls " my dir ")" 

Como por ejemplo con:

 ls "my" "dir" 

y

 ls "my dir" 

La mejor suposición hasta ahora parece ser que usted está pidiendo:

El comando

  Ret = "$ (ls" mi dir ")" 

Es un ejemplo bastante terrible de un comando que contiene cuatro marcas de comillas dobles ( " ). Uno podría ingenuamente esperar que la segunda cita coincidiría con la primera y la cuarta coincidiría con la tercera, así:

  ret="$(ls "my dir")" ↑-----↑ ↑-↑ 

Como, por ejemplo, sucede con

  eat "afternoon snack" dinner "midnight snack" 

En su lugar, "funciona", como sigue:

  Ret = "$ (ls" mi dir ")"
         ↑ ↑ ↑ ↑ ↑
         Unesdoc.unesco.org unesdoc.unesco.org 

¿Por qué se analizan las citas anidadas de esa manera?

Este párrafo de bash (1) puede explicarlo:

Sustitución de Comando


    … Cuando se utiliza el formulario $( command ) , todos los caracteres entre paréntesis forman el comando ….

Supongo que esto significa lo que has observado, es decir, el texto entre el $( y el ) es tratado como si fuera un comando separado, con su propio análisis / emparejamiento de comillas, independiente de los elementos sintácticos fuera de los paréntesis. Admito que, si no está buscando ese significado, es muy difícil interpretarlo.


Pero su pregunta, tal como está escrita, no tiene sentido. Todo depende del significado muy especial de $ a la cáscara. Si cambiamos eso a algún otro símbolo de moneda,

  ret="£(ls "my dir")" 

Entonces sería tratado como dos palabras:

ret="£(ls "my
(seguido por)
dir")"

Porque si un carácter no vacío aparece inmediatamente antes de una cotización de apertura o inmediatamente después de una cotización de cierre, se incluye en la misma cadena que los caracteres incluidos en las comillas. Por ejemplo,

  cat Wal"*"mart 

Busca un archivo llamado Wal*mart , no un archivo llamado Wal , uno llamado * , y otro llamado martWal"*"mart es equivalente a Wal\*mart y "Wal*mart" . Del mismo modo, el siguiente ejemplo muestra cuatro palabras:

  Uno "" dos hebilla "mi" zapato / don \ 't / be / a / "" / cadet sqrt "(2)"
     ↑ ------- ↑ ↑ -------------- ↑ ↑ -------------------- ↑ ↑ - ↑ 

No sé de dónde obtuvo el desglose de tres líneas que mostró en su pregunta.