我正在嘗試運行一個小的 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 腳本傳遞到 shell 命令,而不會遇到所有這些問題?
筆記:我知道暫時重命名檔案可能會更容易,但我發現避免它更具挑戰性。
編輯:
建議的答案都沒有解決我的問題,因此這裡是問題的更具體描述:我正在嘗試執行一個使用的命令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 讀入 shell 變數 v 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
或者,如果您的 shell 提供了 shell-quote 格式說明符,您可以考慮使用它來代替 的find
internal -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