如何將 enscript 應用於超過 60k 的文件?
我想在大量文件(目前 Linux 核心中 git 跟踪的每個文件)上應用 Gnu enscript。我只是為了它。但是,我嘗試了各種方法來將這些文件作為參數傳遞,例如 python 腳本和
$(foo)
,但它說我給它的參數太多。例如,如果我將所有文件的名稱放入files.txt
,每行一個,然後呼叫enscript --color --toc -o out.ps $(<files.txt)
,它會列印錯誤。相同的參數列表與echo
. 為了解決這個問題,我嘗試添加到 enscript 中讀取文件以從文件進行處理的功能,但在進行任何修改之前我無法編譯 enscript 原始碼。有什麼我想念的或者這是不可能的嗎?
問題是您有太多文件無法放入一個命令行(ARG_MAX,Linux 上大約 2 MB)。
有幾種方法可以解決這個問題 - 最明顯的是使用
find
’-exec
選項,它將執行一個命令的多個“批次”,其中包含符合該限制的盡可能多的文件名參數。例如find . -type f -exec sh -c 'enscript --color --toc -o "out.$(date +%s).ps" "$@"' sh {} +
當然,您應該使用任何需要的 find 謂詞來匹配您的文件 - 例如,您可能想要排除 .git 目錄本身,並且可能只包含原始碼和其他文本文件。
請注意,我已將目前時間添加到
out.ps
文件名中。這是因為每批文件find
都會執行一次腳本,我們不希望第二批和後續批次覆蓋第一批的輸出。sh -c ...
還有其他可能更好/更漂亮的方法來為每批輸入文件生成一個唯一的輸出文件名,但這很簡單並且有效並且展示了原理 - 輸出文件名將按創建順序排序。變體(例如,在臨時文件中保存一個計數器)作為練習留給讀者。順便說一句,顯然這將為每批輸入文件生成一個 postscript 輸出文件,每個文件都有自己的 TOC。這與一個包含所有輸入文件和一個 TOC 的輸出文件不太一樣。由於
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
and-r
選項需要 GNU 版本的 xargs。一些古老和/或專有版本的 xargs 甚至不支持-0
,但您不太可能遇到其中之一。這是如何工作的:
兩者都
find
執行xargs
指定的命令,並使用盡可能多的參數在命令行中執行,並重複此操作,直到使用所有參數。