如何将 enscript 应用于 60k 以上的文件?

如何将 enscript 应用于 60k 以上的文件?

我想将 Gnu enscript 应用于大量文件(当前 Linux 内核中 git 跟踪的每个文件)。我只是为了它。但是,我尝试了各种方法来将这些文件作为参数传递,例如 python 脚本 和$(foo),但它说我给了它太多参数。例如,如果我将所有文件的名称放入files.txt,每行一个,然后调用enscript --color --toc -o out.ps $(<files.txt),它会打印错误。相同的参数列表运行得很好echo。为了解决这个问题,我尝试添加 enscript 从文件中读取要处理的文件的功能,但在进行任何修改之前我无法编译 enscript 源代码。我是否缺少某些东西或者这是不可能的?

答案1

问题是文件太多,无法容纳在一个命令行中(ARG_MAX,在 Linux 上大约为 2 MB)。

有几种方法可以处理这个问题 - 最明显的是使用find's-exec选项,它将运行多个“批次”的命令,并使用尽可能多的文件名参数来适应该限制。例如

find . -type f -exec sh -c 'enscript --color --toc -o "out.$(date +%s).ps" "$@"' sh {} +

当然,您应该使用匹配您的文件所需的任何查找谓词 - 例如,您可能希望排除 .git 目录本身,并且可能只包含源代码和其他文本文件。

请注意,我已将当前时间添加到out.ps文件名中。这是因为每批文件find将运行一次脚本,并且我们不希望第二批和后续批次覆盖第一批的输出。sh -c ...还有其他可能更好/更漂亮的方法来为每批输入文件生成唯一的输出文件名,但这很简单并且有效并演示了原理 - 并且输出文件名将按创建顺序排序。变体(例如在临时文件中保存计数器)留给读者作为练习。

顺便说一句,显然这将为每批输入文件生成一个 postscript 输出文件,每个文件都有自己的目录。这与包含所有输入文件和一个目录的一个输出文件不太一样。由于enscript无法从标准输入或文件中获取文件名列表,因此这是您可以获得的最接近的文件名列表。


另一种选择是,如果您已经有了 NUL 分隔文件中的文件列表(如果您绝对确定所有文件名都不会包含换行符,那么换行符分隔应该没问题)是使用xargs.

NUL 分隔:

xargs -0r sh -c 'enscript --color --toc -o "out.$(date +%s).ps" "$@"' sh < files.list

换行符分隔:

xargs -d '\n' -r sh -c 'enscript --color --toc -o "out.$(date +%s).ps" "$@"' sh < files.list

注意:-d-r选项需要 GNU 版本的 xargs。一些古老的和/或专有版本的 xargs 甚至不支持-0,但您不太可能遇到其中之一。


这是如何运作的:

find使用xargs命令行中适合的尽可能多的参数运行指定的命令,然后重复该操作,直到使用所有参数。

相关内容