![引用 ls 输出时出现问题](https://linux22.com/image/94978/%E5%BC%95%E7%94%A8%20ls%20%E8%BE%93%E5%87%BA%E6%97%B6%E5%87%BA%E7%8E%B0%E9%97%AE%E9%A2%98.png)
我想将一些 png 文件合并到 pdf 中。命令
convert *png out.pdf
有效,但顺序错误。事实证明
ls -v *png
给出了我想要的顺序,因此我想将其输出传递给转换。
我努力了
convert `ls -v *png` out.pdf
但这不起作用,因为文件名包含空格和括号。
告诉ls
通过双引号设置文件名
convert `ls -vQ *png` out.pdf
也不起作用,因为引号似乎在替换中被删除了。
我能做些什么?
答案1
如果您有一个最新的基于 GNU 的系统(其sort
提供了类似的-V
自然版本排序),您可以使用它进行排序,并将结果读入数组:
while read -rd '' f; do
files+=("$f")
done < <(find . -maxdepth 1 -name '*png' -print0 | sort -zV)
然后您应该能够在convert
命令中扩展数组:
convert "${files[@]}" out.pdf
答案2
如果您的文件名中没有任何换行符,您可能只需告诉 shellls
仅在换行符上分割输出,默认情况下不分割任何空格即可。这分裂由变量控制IFS
,其中包含的任何字符IFS
都用作分隔符。
IFS=$'\n' # set it to just a newline
convert $(ls -vd ./*.png) output.pdf
如果文件名足够有趣,或者ls
破坏了它们的显示,这可能仍然存在问题。打印到终端时,ls
通常会在多列中列出文件。但是,当输出没有发送到终端时(此处 shell 读取它),它的行为就像-1
已给出一样。
为了实现您开始的想法,您可以使用eval
。
eval: eval [arg ...]
将 ARG 组合成单个字符串,使用结果作为 shell 的输入,并执行生成的命令。
但问题eval
是命令行中的所有内容都会被再次解析,甚至通常安全的东西也不会被解析。想象一个名为 的文件$(touch HELLO)
,如果在命令行中删除这样的名称会发生什么。
另外,如果您采用这种方式,您可能需要使用--quoting-style=shell
not ,-Q
因为它可能更匹配 shell 对特殊字符的处理。 (两者都可能特定于 GNU ls,但我认为-v
也是如此。)
答案3
使用zsh
glob(n)
限定符可以为您提供与 GNU 类似的排序顺序ls -v
:
convert ./*.png(n) out.pdf
在 GNU 系统上,使用bash
、 zsh
、yash
或mksh
:ksh93
eval "files=($(ls --quoting-style=shell-always -vd ./*.png))"
convert "${files[@]}" out.pdf
答案4
使用 GNU Parallel 看起来像这样:
ls -vd ./*png | parallel -Xj1 convert {} out.pdf