Bash: Cita en sustitución de comandos

Bash: Cita en sustitución de comandos

En resumen, quiero usar directorios enumerados por un comando en un findcomando:

find $(produces_dir_names --options...) -find-options...

El problema surge con los espacios en blanco en los nombres de los directorios. Pensé que citarlos en el resultado del comando de producción (que puedo cambiar) sería suficiente:

"a" "a b" "a b c"

pero bash se queja:

find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory

Como puede, ver bashdividirá la salida del comando en espacios, incluso con las comillas. Intenté manipularlo IFSy configurarlo \n, pero mi comprensión parece demasiado limitada para que funcione.

La única solución que encontré fue en esta pregunta de Stack Overflow: sustitución del comando bash eliminar cita, es decir, poner un evaldelante, pero esto parece un poco feo.

Mis preguntas:

¿Existe una manera fácil y cómo se vería escribir esta sustitución, sin eval?

¿Son necesarias las citas?

Ejemplo (produciendo el mismo resultado):

find $(echo '"a" "a b" "a b c"')

Respuesta1

Tal vez en dos líneas

IFS=$'\n' DIRS=( $(produces_dir_names --options...) ) 
find "${DIRS[@]}" -find-options...

Ejemplo:

$ mkdir -p "/tmp/test/a b/foo" "/tmp/test/x y/bar"

$ IFS=$'\n' DIRS=( $(printf "/tmp/test/a b\n/tmp/test/x y\n") )
$ find "${DIRS[@]}" -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar

Pero en general éste no es un buen estilo. Por ejemplo, tendrá problemas si su DIRS contiene nuevas líneas. Mejor arregle sus "produces_dir_names" para imprimir cadenas terminadas en bytes nulos. Respecto a mi ejemplo, esto sería algo como:

$ printf "/tmp/test/a b\0/tmp/test/x y\0" | xargs -0 -I '{}' find '{}' -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar

Si no puedes corregir "produces_dir_names", con respecto a mi último comentario, la solución más general sería la siguiente:

produces_dir_names --options... | tr '\n' '\0' | xargs -0  -I '{}' find '{}' -find-options...

Aún hay problemas con las "nuevas líneas" a menos que arregles "produces_dir_names" para evitarlos tr.

Respuesta2

la respuesta de rudimeieres bueno, específicamente, la parte sobre la modificación produces_dir_names para imprimir cadenas terminadas en nulo, pero puede que no sea obvio por su respuesta que se ejecuta finduna vez para cada directorio. Si esto es lo suficientemente bueno, entonces está bien. Pero, por supuesto, es posible invocar find con múltiples puntos de partida; p.ej,

encontrar  dirección 1 dirección 2 dirección 3  -opciones de búsqueda...

y de la pregunta se desprende que eso es lo que quieres. Esto puede hacerse de la siguiente manera:

printf "a\0a b\0a b c" | xargs -0 sh -c 'buscar "$@" -opciones de búsqueda...' sh

Esto hace xargsque se invoque sh -cuna vez, con todos los nombres de directorio agregados al comando. Luego, el shell se expandirá "$@"a una lista de esos nombres de directorio.

PD: Si produces_dir_namesenumera demasiados nombres de directorios para ponerlos en una línea de comando, xargsse verá obligado a generar algunos comandos. Úselo xargs --verbosepara ver qué comandos xargsse generan.

Respuesta3

Sólo para aclarar el misterio de los mensajes de error que recibe:

find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory

La respuesta es queLa eliminación de comillas de Bash no elimina las comillas queresultadode la sustitución de mando.

DeLESS='+/^ *Quote Removal' man bash

Quote Removal
    After the preceding expansions, all unquoted occurrences of the charac-
    ters  \,  ', and " that did not result from one of the above expansions
    are removed.

Las "expansiones anteriores" a las que se hace referencia incluyen:

EXPANSION
   Brace Expansion
   Tilde Expansion
   Parameter Expansion
   Command Substitution
   Arithmetic Expansion
   Process Substitution
   Word Splitting
   Pathname Expansion
   Quote Removal

información relacionada