如何防止雙重轉義?
我正在嘗試將一堆圖像放在一起成pdf。我跑了
gm convert *.jpg out.pdf
,它工作了,但圖像的順序不正確。我發現它們的
ls -v
順序正確,所以我嘗試gm convert
ls -v *.jpgout.pdf
了,但失敗了,因為文件名稱中有空格。所以我檢查了 ls 選項並嘗試了
gm convert
ls -Qv *.jpgout.pdf
但gm convert
ls -bv *.jpgout.pdf
都失敗了,因為據我所知,文件名被轉義了兩次(在第一種情況下使用 ",在第二種情況下使用 \ 在空格之前)。為什麼會這樣發生了,我怎樣才能正確地轉義文件名,即只有一次?如果相關的話,我正在使用 zsh。
您不能以這種方式使用轉義。您可以使用引號或反斜杠來理解它們,例如 shell 解析。
沒有什麼可以逃避在變數擴展或命令替換時完成的單詞拆分(這與命令行的 shell 解析(標記化)不同)。
您可以做的是將內部欄位分隔符更改為
$IFS
僅在換行符上拆分(但請注意,除了 with 之外zsh
,您還需要禁用文件名生成(儘管*.jpg
顯然不是為了擴展),這是在不帶引號的命令替換時完成的另一件事,除非您可以保證沒有文件名包含萬用字元):set -f # disable filename generation IFS=' ' # set IFS to newline character IFS=$'\n' # alternative for ksh/zsh/bash gm convert $(set +f; ls -v ./*.jpg) out.pdf # you also need ./ in case file # names start with -
(假設所有文件名都不包含換行符)
set -f
inzsh
(除非在 sh/ksh 仿真中)禁用讀取rc
文件(想想zsh -f
,csh -f
),一旦 shell 已經啟動,它就沒有效果,所以是無害的。使用
zsh
,您可以將其縮短為:gm convert ${(f)"$(ls -v ./*.jpg)"} out.pdf
(f)
縮寫(ps:\n:)
是在換行符處拆分。或者,您可以使用
ls
引用來建構一個 shell 命令行(如果您願意,可以使用 shell 語法中的 shell 程式碼)傳遞給eval
它將讓 shell 評估它並執行它:用
ksh93
,zsh
或bash
:eval "images=($(ls --quoting-style=shell -v ./*.jpg))" gm convert "${images[@]}" out.pdf
但是使用
zsh
,您可以簡單地執行以下操作:gm convert ./*.jpg(n) out.pdf
(n)
是一個萬用字元,它告訴 shell 對生成的文件名進行數字排序。