60k以上のファイルにenscriptを適用するには?

60k以上のファイルにenscriptを適用するには?

私は多数のファイル(現在のLinuxカーネルでgitによって追跡されているすべてのファイル)にGnu enscriptを適用したいと思います。私はそこにいます。しかし、これらのファイルをPythonスクリプトなどのパラメータに渡すためにさまざまな方法を試しましたが、$(foo)パラメータを指定しすぎたとします。たとえば、すべてのファイルの名前をfiles.txt1行に1つずつ入力してから呼び出すと、enscript --color --toc -o out.ps $(<files.txt)エラーが表示されます。同じパラメータリストがうまく機能しますecho。この問題を解決するために、enscriptは処理するファイルから読み取る機能を追加しようとしましたが、変更する前にenscriptソースコードをコンパイルできませんでした。私が何かを見逃しているのか、それとも不可能なのでしょうか?

答え1

問題は、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ファイルバッチごとに一度実行され、2番目とそれ以降のバッチが最初のバッチの出力を上書きしたくないためです。sh -c ...各入力ファイルのバッチごとに一意の出力ファイル名を生成するためのより良い、よりきれいな方法がありますが、これは単純で動作し、原理を示しています。出力ファイル名は生成された順序でソートされます。一時ファイルにカウンタを保存するなどのバリエーションは、読者の練習問題として残されます。

しかし、明らかに、これは入力ファイルの各バッチに対してそれぞれ独自のディレクトリを持つPostScript出力ファイルを生成します。これは、すべての入力ファイルとディレクトリを含む1つの出力ファイルを持つものとは異なります。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これらのバージョンの1つに触れる可能性はほとんどありません。


動作原理:

コマンドラインに合うだけの引数を使用して指定されたコマンドを実行findし、すべての引数が使用されるまで繰り返します。xargs

関連情報