Экранирование переменных gawk для команд оболочки

Экранирование переменных gawk для команд оболочки

Я пытаюсь запустить небольшой скрипт gawk, который будет запускать определенные команды оболочки с помощью system(). Я хочу получить список файлов findи запустить скрипт следующим образом:

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

Проблема в том, что в этих файлах есть специальные символы, такие как пробелы, кавычки и скобки. Например:

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

Я перепробовал всевозможные цитаты, например, такие:

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

И это:

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

Я получаю всевозможные ошибки, некоторые из них связаны sh -cс gawk...

Есть ли способ передать запись $0или любые другие переменные из скрипта gawk в команду оболочки, не сталкиваясь со всеми этими проблемами?

Примечание:Я знаю, что было бы проще просто временно переименовать файлы, но мне кажется сложнее этого избежать.

РЕДАКТИРОВАТЬ:

Ни один из предложенных ответов не решил мою проблему, поэтому вот более конкретное описание проблемы: Я пытаюсь запустить команду, которая использует2Переменные awk. Примеры:

Если я запущу:

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

Я не получаю сообщение об ошибке, потому что я цитирую, FILEи поскольку текст не содержит двойных кавычек, все проходит нормально.

Но если я запущу:

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

Даже когда я цитирую его, я получаю ошибку, metaflacчто файл flac не найден. При чтении сообщения об ошибке я вижу, что имя файла было разделено на отдельные слова.

решение1

Вы можете заменить system("<command> \"$0\"")его способностью awk писать в процесс, т. е. print $0 | "pre;<command> \"$v\"", гдепредварительночасть будет читать stdin в переменную оболочки v. В bash это будет read -r v. Вы получите, например, это:

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

Если вы хотите справиться с ужасными вещами, такими как переводы строк в именах файлов, вы можете использовать маршрут print0 в вашем find и, если ваш awk принимает это RS='\0', для bash у вас есть:

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

решение2

В конкретном случае пробелов и одинарных кавычек будет достаточно заключить строку в двойные кавычки:

$ 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

В качестве альтернативы, если ваша оболочка предоставляет спецификатор формата кавычек оболочки, вы можете рассмотреть возможность использования его вместо findвнутреннего -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

help printfНапример , из bash:

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

Связанный контент