いつ `見つけるか。-exec COMMAND {} + `COMMANDを複数回実行しますか?


8

私が行った場合

find . -exec echo {} +

すべてのパスを1行で出力しますecho。つまり、コマンドは1回だけ実行されます。

しかし、によるとman find

-exec command {} +
    ... the number of invocations of the command will 
be much  less  than  the  number  of matched files. ...

状況によっては、コマンドが複数回実行されるようです。私は正しいですか?例示してください。

回答:


7

POSIXで定義されているfind -exec utility_name [argument ...] {} + as:

1次式の終わりは、<セミコロン>または<プラス記号>で区切られます。2つの文字「{}」のみを含む引数の直後に続く<plus-sign>のみが、1次式の終わりを区切るものとします。<plus-sign>の他の使用は、特別なものとして扱われません。1次式が<セミコロン>で区切られている場合、ユーティリティutility_nameはパス名ごとに1回呼び出され、ユーティリティが終了ステータスとしてゼロ値を返す場合、1次はtrueと評価されます。utility_name又は引数 2文字のみを含有する「{}」電流パス名に置き換えなければなりません。もしutility_nameまたは引数stringには2つの文字 "{}"が含まれていますが、2つの文字 "{}"だけではなく、findがこれらの2つの文字を置き換えるか、変更せずに文字列を使用するかは実装定義です。

1次式が<plus-sign>で区切られている場合、1次式は常にtrueと評価され、1次式が評価されるパス名は集合に集約されます。ユーティリティutility_name は、集約されたパス名のセットごとに1回呼び出されます。各呼び出しは、セットの最後のパス名が集約された後に始まり、検索ユーティリティが終了する前に、次のセット(存在する場合)の最初のパス名がこのプライマリに集約される前に完了しますが、それ以外の場合、呼び出しは他のプライマリの評価の前、最中、または後に発生します。いずれかの呼び出しが終了ステータスとしてゼロ以外の値を返す場合、検索 ユーティリティはゼロ以外の終了ステータスを返します。2つの文字「{}」のみを含む引数は、集約されたパス名のセットで置き換えられます。各パス名は、集約されたのと同じ順序で呼び出されたユーティリティに個別の引数として渡されます。2つ以上のパス名のセットのサイズは、ユーティリティの実行によってシステムの{ARG_MAX}制限を超えないように制限されます。2つの文字「{}」を含む引数が複数ある場合の動作は規定されていません。

見つかったファイル名の長さセットがsystemを超えるARG_MAXと、コマンドが実行されます。

getconfARG_MAXを使用して取得できます。

$ getconf ARG_MAX
2097152

一部のシステムでは、実際の値ARG_MAXが異なる場合があります。詳細については、ここを参照してください。


find / -exec echo | wc文字数と行数の比率を使用して測定を行った実験を実行したところ、によって使用されるコマンド行の最大長findは、理論上のPOSIX制限よりも大幅に短く、Size of command buffer we are actually usingからの出力の行にかなり近いことがわかりましたxargs --show-limits。これはLinuxに当てはまり、Mac OSでの値は表示されませんがfind、Mac OSのの実装に当てはまる場合がありますxargs。なぜこれが起こるのかについて何か考えはありますか?
pqnet 2014

--show-limitsはPOSIXで指定されてxargsいません。MacOSの実装ではサポートされていません。find / -exec echo | wc動作しません。ARG_MAX戻りバイトを覚えておいてください。そして、それはexec(3)関数への引数の最大長です。
cuonglm 14

--show-limitsはPOSIXではないことを知っていますが、これはが使用する引数の最大長ではなく、findより小さな値を使用します。なぜうまくいかないのかわかりませんfind / -exec echo | wc。私の意見では、実際の価値を推定するのに良い方法です(そして、私が見ることができることから、を使用するよりも優れていますgetconf ARG_MAX)。また、私のファイルシステムはすべてではないにしてもほとんどの場合ASCII文字であるため、文字数はバイト数とほぼ同じです。
pqnet 2014

@pqnet:isnteadを使用しfind / -exec sh -c 'echo $@ | wc -c' _ {} +ます。
cuonglm 2014

申し訳ありませんが、間違って書いたので実際に使用しましたfind / -exec echo {} + | wc -lc
pqnet '29

7

POSIXシステムの新しいプロセスには、引数リストの最大長があります。findファイルのパスがこれより長い場合、実行が分割されます。Linuxでの制限を確認するには、次を使用しますxargs --show-limits(Mac OSでは機能しません。誰かがより良い代替案を知っている場合は、ここにコメントしてください)

編集: Gnoucの答えから直接盗まれた、引数リストの最大長を取得するPOSIXの方法はgetconf ARG_MAXです。しかし、私は自分のmac osマシンで実験を行ったところ、findその数の半分以上を使用しているようです。これは、機能するシステムでxargs --show-limitsは、引数の最大長を使用しないことを示しています(この場合も、その半分の数を使用します)が、説明を見つけることができなかったという事実と一致しています。そのため。

編集2:find各呼び出しでいくつのパラメータがくっつくかを決定する唯一の信頼できる方法は、たとえば実行することによって実験することです

find / -exec echo {} + | wc -cl

からの出力には呼び出しfindごとに1行があるためecho、を使用してそれらをカウントすることができwc -lます。echoed の合計バイト数は、wc -c代わりにの出力です。1つをもう1つで除算すると、各コマンド呼び出しのパラメーターの平均バイト数を取得します(丸めのため、値はわずかに低くなりますが、システム内のパスの平均長の約半分です)。


xargs多くのプログラムはいくつかの追加の引数を付加し、その引数を他のプログラムに渡すため、は引数の最大長を完全には使用しません。場合はxargs、絶対最大塗りつぶしの引数は、このようなプログラムが破損、ので、それらの余分な引数の余地はないだろう。
hvd 2014

@hvdは理にかなっています。しかし、その後、によって使用されているどのくらいのバッファの知るPOSIXの方法があるxargsかはfind
pqnet 2014

非常に長い引数のリストを使用してそれを実行し、最初の呼び出しで渡された引数の数(のようなものyes . | xargs | head -n 1 | wc -c)を判別し、それをの出力と比較できますgetconf ARG_MAX。しかし、実際に自分のシステムで試してみると、違いが非常に大きくなるため、私が認識している以上の違いがあるようです。
hvd 2014

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.