を使用して特定のシェル コマンドを実行する小さな 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 スクリプトからシェル コマンドに渡す方法はありますか?
注記:一時的にファイル名を変更する方が簡単だったかもしれないことは分かっていますが、それを避けるのはより困難だと思います。
編集:
提案された回答のどれも私の問題を解決しなかったため、ここでは問題のより具体的な説明を示します。私は、2awk 変数。例:
実行した場合:
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); }'
ファイル名の改行などの厄介なものを処理したい場合は、find で print0 ルートを使用できます。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