Escapar de variables gawk para comandos de shell

Escapar de variables gawk para comandos de shell

Estoy intentando ejecutar un pequeño script gawk que ejecutará ciertos comandos de shell usando system(). Quiero obtener la lista de archivos findy ejecutar el script así:

find <arguments> -printf "%f\n" | script.awk

El problema es que estos archivos tienen caracteres especiales como espacios, comillas y paréntesis. Por ejemplo:

$ ls
'Aujourd'\''hui C'\''est Toi (Orchestral).flac'

Probé todo tipo de citas como las siguientes:

system("<command> \""$0"\"")

Y esto:

system("<command> \'"$0"\'")

Recibo todo tipo de errores, algunos de estos errores son de sh -cy otros son de gawk...

¿Hay alguna manera de pasar el registro $0o cualquier otra variable del script gawk a un comando de shell sin encontrar todos estos problemas?

Nota:Sé que podría haber sido más fácil cambiar el nombre de los archivos temporalmente, pero me resulta más difícil evitarlo.

EDITAR:

Ninguna de las respuestas sugeridas resolvió mi problema, así que aquí hay una descripción más específica del problema: Estoy intentando ejecutar un comando que usa2variables extrañas. Ejemplos:

Si corro:

system("metaflac --show-tag=ARTIST \""FILE"\"")

No recibo ningún error porque cito FILEy como no contiene comillas dobles, va bien.

Pero si ejecuto:

system("metaflac --set-tag=ARTIST="AWK_VAR_WITH_ARTIST_VALUE" "\"FILE\")

Incluso cuando lo cito, aparece un error que indica metaflacque no se encontró el archivo flac. Al leer el mensaje de error, veo que el nombre del archivo se dividió en palabras separadas.

Respuesta1

Podrías reemplazarlo system("<command> \"$0\"")por la capacidad de awk para escribir en un proceso, es decir print $0 | "pre;<command> \"$v\"", dondepreparte leería stdin en la variable de shell v. En bash esto sería read -r v. Terminas con esto, por ejemplo:

awk 'BEGIN{ cmd="read -r v; ls -ld \"$v\"" }
     { print $0 | cmd; close(cmd); }'

Si desea manejar cosas horribles como nuevas líneas en los nombres de archivos, puede ir a la ruta print0 en su búsqueda y, si su awk lo acepta RS='\0', tiene para bash:

find . -print0 |
awk -v RS='\0' '
 BEGIN{ cmd="read -r -d \"\" v; ls -ld \"$v\"" }
 { print $0 "\x00" | cmd; close(cmd); }'

Respuesta2

Para el caso específico de espacios y comillas simples, debería ser suficiente encerrar la cadena entre comillas dobles:

$ find -name 'Aujour*' -printf "%f\n" | awk '{system("ls -l \""$0"\"")}'
-rw-rw-r-- 1 user user 0 May 26 11:27 Aujourd'hui C'est Toi (Orchestral).flac

Alternativamente, si su shell proporciona un especificador de formato de comillas de shell, podría considerar usarlo en lugar de findinternal -printf:

$ find -name 'Aujour*' -exec printf '%q\n' {} \; | awk '{system("ls -l "$0)}'
-rw-rw-r-- 1 user user 0 May 26 11:27 ./Aujourd'hui C'est Toi (Orchestral).flac

Desde help printfen bashpor ejemplo:

%q  quote the argument in a way that can be reused as shell input

información relacionada