Shell

如何防止雙重轉義?

  • March 13, 2013

我正在嘗試將一堆圖像放在一起成pdf。我跑了gm convert *.jpg out.pdf,它工作了,但圖像的順序不正確。

我發現它們的ls -v順序正確,所以我嘗試gm convert ls -v *.jpg out.pdf了,但失敗了,因為文件名稱中有空格。

所以我檢查了 ls 選項並嘗試了gm convert ls -Qv *.jpg out.pdfgm convert ls -bv *.jpg out.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 -fin zsh(除非在 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,zshbash:

eval "images=($(ls --quoting-style=shell -v ./*.jpg))"
gm convert "${images[@]}" out.pdf

但是使用zsh,您可以簡單地執行以下操作:

gm convert ./*.jpg(n) out.pdf

(n)是一個萬用字元,它​​告訴 shell 對生成的文件名進行數字排序。

引用自:https://unix.stackexchange.com/questions/67735