CP:コピーユーティリティの最大ソースファイル数引数


11

/ src /の下に無数のファイルがあることを考慮してください

cp /src/* /dst/

cpいくつのファイルが正常に処理されますか?


2
引数リストが長すぎる場合(*が行うのは、グロブに一致するすべてのファイルのリストに展開されることを思い出してください)、eg IFS="\n" for file in /src/*; do mv "$file" /dst/; doneまたはを使用して回避できますrsync -a /src/ /dst/
DopeGhoti 2014年

回答:


18

これは、システムとバージョン、引数の数とサイズ、環境変数名の数とサイズに大きく依存します。

伝統的にUnixでは、(によって報告されたgetconf ARG_MAX)制限は多かれ少なかれ次の累積サイズにありました:

  • 引数文字列の長さ(終了文字列を含む'\0'
  • それらの文字列へのポインタの配列の長さ、つまり通常64ビットシステムでは引数あたり8バイト
  • 環境文字列(終了文字列を含む'\0')の長さvar=value。環境文字列は慣例によりのようなものです。
  • それらの文字列へのポインタの配列の長さ、つまり通常64ビットシステムでは引数あたり8バイト

これcpも引数としてカウントされることを覚えておいてください(最初の引数です)。

Linuxでは、バージョンによって異なります。固定スペースではなくなった最近の動作が変更されました。

Linux 3.11でのチェックでgetconf ARG_MAXは、スタックサイズに設定された制限の4分の1が報告されるようになりました(512kiB未満の場合は128kiB)。

zsh以下の構文):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576

その制限は、引数と環境文字列の累積サイズといくつかのオーバーヘッドにあります(ページ境界での配置の考慮に疑いがあります)。ポインターのサイズは考慮されません。

限界を探して、私は得ます:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true

その場合の分割前の最大累積サイズは次のとおりです。

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462

だからといって、100万個の空の引数を渡せるわけではありません。64ビットシステムでは、100万の空の引数により8 MBのポインターリストが作成されます。これは、私のスタックサイズ4MiBを超えます。

$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed     /bin/true ${=${(l.1000000..:.)${:-}}}

(E2BIGエラーではないことに気づくでしょう。execveシステムコール以降にある場合でも、プロセスがどの時点で強制終了されるかはわかりません)。

また、(Linux 3.11でも)スタックのサイズに関係なく、単一の引数または環境文字列の最大サイズは128kiBであることに注意してください。

$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK

共有していただけますか、どのようにして164686番号を思い付きましたか?つまり、そのシーケンスはどのように2097152ARG_MAXサイズ以下になると計算しましたか?
Sergiy Kolodyazhnyy

14

これは、システム間で変化する可能性のあるARG_MAXの値に依存します。システム実行の値を見つけるには(例として私の結果を表示):

$ getconf ARG_MAX
2097152

これはcpシェルやシェルとは何の関係もありません。これはカーネルによって課せられる制限であり、exec()引数がより大きい場合は()コマンドを実行しませんARG_MAX。したがって、指定した引数リストの長さがcpARG_MAXより大きい場合、cpコマンドはまったく実行されません。

あなたの主な質問に答えるcpために、それはあまり多くの引数で実行されることはないので、ファイルを処理しません。また、これは引数の数ではなく長さに依存することにも触れておきます。非常に少数の非常に長いファイル名で同じ問題が発生する可能性があります。


これらのエラーを回避する方法は、コマンドをループで実行することです。

for file in /src/*; do cp "$file" /dst/; done

これは、などの低レベルの言語でもC、ARG_MAXと本当に長いファイル名で問題が発生する可能性があることを意味しますか?
ハロルドフィッシャー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.