具有数字顺序的 Glob

具有数字顺序的 Glob

我的目录中有以下 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 -vGNU 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>.pdfb<number>.pdfc<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来说就是这样的命令,你需要“./“ 代替 ”“...如果一个不起作用,请尝试另一个)

相关内容