我正在尝试将一堆图像合并成一个 pdf 文件。我跑了gm convert *.jpg out.pdf
,它成功了,但图像的顺序不正确。
我发现ls -v
它们的顺序正确,所以我尝试了gm convert `ls -v *.jpg` out.pdf
,但失败了,因为文件名称中包含空格。
所以我检查了 ls 选项并尝试了gm convert `ls -Qv *.jpg` out.pdf
,gm convert `ls -bv *.jpg` out.pdf
但都失败了,因为据我所知,文件名被转义了两次(在第一种情况下使用 \" ,在第二种情况下在空格前使用 \\ )。
为什么这是这样发生了,如何正确转义文件名,即仅使用一次 zsh(如果相关的话)。
答案1
你不能用这种方式转义。您可以使用引号或反斜杠来理解它们,例如 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
in 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
,zsh
或bash
:
eval "images=($(ls --quoting-style=shell -v ./*.jpg))"
gm convert "${images[@]}" out.pdf
但是使用zsh
,您可以简单地执行以下操作:
gm convert ./*.jpg(n) out.pdf
(n)
是一个通配限定符,告诉 shell 按数字方式对生成的文件名进行排序。