我的目录中有以下 pdf 文件列表:
c0.pdf c12.pdf c15.pdf c18.pdf c20.pdf c4.pdf c7.pdf
c10.pdf c13.pdf c16.pdf c19.pdf c2.pdf c5.pdf c8.pdf
c11.pdf c14.pdf c17.pdf c1.pdf c3.pdf c6.pdf c9.pdf
我想使用 Ghostscript 按数字顺序连接这些(与此类似):
gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf
但是 shell 扩展顺序并不重现数字的自然顺序而是字母顺序:
$ for f in *.pdf; do echo $f; done
c0.pdf
c10.pdf
c11.pdf
c12.pdf
c13.pdf
c14.pdf
c15.pdf
c16.pdf
c17.pdf
c18.pdf
c19.pdf
c1.pdf
c20.pdf
c2.pdf
c3.pdf
c4.pdf
c5.pdf
c6.pdf
c7.pdf
c8.pdf
c9.pdf
如何在扩展中实现所需的顺序(如果可能,无需手动添加0
-padding 到文件名中的数字)?
我找到了使用建议ls | sort -V
,但无法让它适用于我的特定用例。
答案1
再一次,zsh 的 glob 限定符前来救援。
echo *.pdf(n)
答案2
根据您的环境,您可以使用ls -v
GNU coreutils,例如:
gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
-sOutputFile=out.pdf $(ls -v)
或者,如果您使用的是最新版本的 FreeBSD 或 OpenBSD:
gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
-sOutputFile=out.pdf $(ls | sort -V)
答案3
如果所有相关文件都有相同的前缀(即数字之前的文本;c
在本例中),您可以使用
GS …参数… c?.pdf c??.pdf
c?.pdf
扩展到c0.pdf
c1.pdf
…… c9.pdf
。
c??.pdf
扩展到c10.pdf
c11.pdf
... c20.pdf
(并且最多扩展到c99.pdf
,如果适用)。虽然包含路径名扩展字符的每个命令行单词都扩展为根据变量排序(整理)的文件名列表LC_COLLATE
,但相邻通配符(通配符)扩展所产生的列表不会合并;它们只是简单地串联起来。 (我似乎记得shell手册页曾经明确指出过这一点,但现在找不到了。)
当然,如果文件可以达到c999.pdf
,你应该使用c?.pdf c??.pdf c???.pdf
。不可否认,如果您有很多数字,这可能会变得乏味。你可以稍微缩写一下;例如,对于(最多)五位数字,您可以使用c?{,?{,?{,?{,?}}}}.pdf
.如果您的文件名列表很稀疏(例如,有 ac0.pdf
和 a c12345.pdf
,但不一定是中间的每个数字),您可能应该设置该nullglob
选项。否则,如果(例如)您没有包含两位数的文件,您将得到c??.pdf
传递给程序的文字参数。
如果您有多个前缀(例如,、 和,带有一位或两位数字),您可以使用明显的强力方法:a<number>.pdf
b<number>.pdf
c<number>.pdf
a?.pdf a??.pdf b?.pdf b??.pdf c?.pdf c??.pdf
或将其折叠为{a,b,c}?{,?}.pdf
.
答案4
只是引用并修复雷神的答案...永远不要解析 ls!
您可以使用sort -V
(非 POSIX 扩展进行排序):
printf '%s\0' ./* | sort -zV \
| xargs -0 gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH \
-sDEVICE=pdfwrite -sOutputFile=out.pdf
(对于某些命令,显然对于gs来说就是这样的命令,你需要“./“ 代替 ”“...如果一个不起作用,请尝试另一个)