如何雙引號文件的萬用字元模式?
我已經看到了一堆與此類似的問題,但沒有一個完全相同。
我有一個文件目錄,我想使用萬用字元擴展將其作為單個雙引號參數傳遞給命令。
文件
a.ext b.ext c.ext
預期用途
command --flag "a.ext b.ext c.ext"
目前,我正在使用
command --flag $(echo \"$(echo ./*.ext)\")
,但這不起作用,而且看起來也不必要地複雜。有沒有一種簡單的方法可以做到這一點?
如果您想使用 SPC 字元連接 glob 擴展產生的文件名,您可以將它們儲存在位置參數中並用於
"$*"
執行連接:set -- ./*.ext IFS=' ' # SPC is the first character of $IFS by default, we're setting it # here in case that code is called in a context where it has been # modified before. files_joined_with_SPC="$*" cmd --flag "$files_joined_with_SPC"
或者:
cmd --flag "$*"
當然直接(儘管它更容易忘記它取決於 的目前值這一事實
$IFS
)。以上是標準的 POSIX
sh
語法。在zsh
/ksh93
/bash
/mksh
/yash
中,您還可以使用數組代替位置參數:files=(./*.ext) IFS=' '; files_joined_with_SPC="${files[*]}"
使用
zsh
,您還可以使用:files=(./*.ext) cmd --flag "${(j[ ])files}"
或使用匿名函式:
(){ cmd --flag "${(j[ ])argv}"; } ./*.ext
我們明確地請求
j
使用 SPC 進行操作,而不必依賴像$IFS
.現在,請注意 SPC 與文件路徑中的任何字元一樣有效。除了 NUL 之外的任何字元在文件路徑中都是有效的(實際上在大多數係統上除了 0 之外的任何字節值,這些字節甚至不必形成有效字元),但是 NUL 不能作為參數傳遞給執行的命令。
你沒有說那*
command
*是什麼(順便說一下是command
標準 shell 內置命令的名稱,我更喜歡使用cmd
佔位符),但如果那cmd --flag list
是為了接受任何文件名列表,SPC 分隔,它們必須有一種讓使用者SPC
在文件名中指定 a 的方法。那可能是
cmd --flag 'with\ space.ext other.ext'
orcmd --flag 'with%20space.ext other.ext
,cmd --flag 'with\040space.ext other.ext'
, 等等。在這種情況下,在為 建構該參數時
cmd --flag
,您可能必須先轉義文件名中的該 SPC(可能還有\
字元%
),然後再將它們與 SPC 連接。在
ksh93
//zsh
/bash
中yash
,可以這樣做:escaped_files=("${files[@]//\\/\\\\}") # \ escaped as \\ escaped_files=("{files[@]// /\\ }") # SPC escaped as \SPC # more characters may need to be escaped such as other whitespace # or quoting characters, depending on the exact syntax expected by # cmd for the --flag option. IFS=' '; escaped_files_joined_with_SPC="$*" cmd -- flag "$escaped_files_joined_with_SPC"
(儘管要注意使用字元編碼的語言環境,例如 GB18030、BIG5 ……其中某些字元包含反斜杠的編碼(字節 0x5c)。您的外殼可能不會轉義那些 0x5c 字節,但
cmd --flag
如果不解碼,仍可能將它們視為反斜杠根據語言環境的字元集的參數)。命令獲取文件名列表的更可靠/方便的方法是將它們作為單獨的參數(而不是作為選項的參數),或者作為
cmd --flag 'file 1.ext' --flag 'file 2.ext'...
.