多数のファイルをコピー中に「引数リストが長すぎます」エラー


12

私は次のコマンドを使用しています:

\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/

そして、私はエラーが発生しています:

-bash: /bin/cp: Argument list too long

私も試しました:

ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/

まだ-bash:/ bin / ls:引数リストが長すぎます

何か案は?


1つのディレクトリから別のディレクトリにすべてのjpgをコピーしようとしていますが、新しいファイルと更新されたものだけがコピーされます。
アイスリザード2009

lsこのようなことをするように設計されていません。を使用しfindます。
追って通知があるまで一時停止します。

問題はlsではなく、シェルがlsに渡す引数の数にあります。viまたは非組み込みコマンドでも同じエラーが発生します。
クリス

しかしls特にこれを行うようには設計されていません:mywiki.wooledge.org/ParsingLs
通知があるまで一時停止します。

確かに、この場合、エラーはlsの解析エラーによるものではなく、たまたまlsである新しいプロセスに10億の引数を渡すことによるものです。lsの不適切な使用に加えて、Unixのリソース/設計の制限にぶつかることもあります。この場合、患者は胃の痛みと足の骨折の両方を患っています。
クリス

回答:


19

* .jpgは、シェルが処理できるよりも長いリストに展開されます。代わりにこれを試してください

find  /home/ftpuser/public_html/ftparea/ -name "*.jpg" -exec cp -uf "{}" /your/destination \;

find / home / ftpuser1 / public_html / ftparea / -name "* jpg" -exec cp -uf "{}" / home / ftpuser2 / public_html / ftparea /を使用すると、次のエラーが見つかりました。
アイスリザード2009

cpの最後の引数が欠落している、と回答者はあなたに言った。実装を再確認してください。この回答では、「*。jpg」のドットが欠落していることに注意してください。これは誤動作につながる可能性があります(たとえば、「myjpg」という名前のディレクトリ)。その場合、パラノイですが、-typeファイルを使用してコピーする内容を厳密に指定する方が安全な場合があります(dirs、シンボリックリンクなどの影響を防ぐため)
drAlberT 09

よく調べた後、「\;」を見逃しました -execが実行するコマンドを終了します。愚かな私!
アイスリザード2009

@AlberT:欠落しているドットについての頭に感謝します。それはタイプミスでした。回答が更新されました。
ショーンチン

cpで処理できないわけではありません。シェルはできません。
d -_- b

6

システムコマンドの引数リストの長さには最大の制限があります。この制限はMAX_ARG_PAGES、カーネルのコンパイル時の値に基づいて分布固有であり、カーネルを再コンパイルしないと変更できません。

シェルによるグロビングの処理方法により、同じ引数( "* .jpg")を使用すると、ほとんどのシステムコマンドに影響します。globは最初にシェルによって処理されてからコマンドに送信されるため、コマンドは次のようになります。

cp -uf *.jpg /targetdir/

シェルと本質的には、次のように記述します。

cp -uf 1.jpg 2.jpg ... n-1.jpg n.jpg /targetdir/

多くのjpegを扱っている場合、これは非常に迅速に管理不能になる可能性があります。命名規則と実際に処理する必要があるファイルの数に応じて、一度にディレクトリの異なるサブセットでcpコマンドを実行できます。

cp -uf /sourcedir/[a-m]*.jpg /targetdir/
cp -uf /sourcedir/[n-z]*.jpg /targetdir/

これは機能する可能性がありますが、ファイルリストを便利なグロブ可能ブロックにどれだけうまく分割できるかに基づいて、正確にどれだけ効果があるかが決まります。

グロッバブル。私はその言葉が好きです。

findxargsなどの一部のコマンドは、非常に大きなサイズの引数リストを作成せずに大きなファイルリストを処理できます。

find /sourcedir/ -name '*.jpg' -exec cp -uf {} /targetdir/ \;

-exec引数は、findで見つかったファイルごとにコマンドラインの残りを1回実行し、{}を見つかった各ファイル名に置き換えます。以来のcpコマンドは一度に1つのファイル上で実行され、引数リストの制限は問題ではありません。

これは、各ファイルを個別に処理する必要があるため、時間がかかる場合があります。xargsを使用すると、より効率的なソリューションを提供できます。

find /sourcedir/ -name '*.jpg' -print0 | xargs -0 cp -uf -t /destdir/

xargsがが提供する完全なファイルリスト取ることができます検索し、かつ管理可能なサイズと、ランの引数リストの中にそれを打破CPこれらのサブリストのそれぞれに。

もちろん、カーネルに再コンパイルして、より大きな値を設定する可能性もありますMAX_ARG_PAGES。しかし、カーネルの再コンパイルは、この回答で説明するよりも多くの作業です。


これがなぜ投票されたのか、私にはわかりません。これがなぜ起こっているのかを説明していると思われる唯一の答えです。xargsを最適化として使用することを提案しなかったからでしょうか?
クリス

xargsソリューションに追加されましたが、ダウン投票は私の詳細に露骨に間違っているためであり、それが何であるかを誰も教えてくれません。:(
goldPseudo 09

xargs結果として生じるコマンド呼び出しの数がはるかに少ないため、はるかに効率的であるようです。私の場合、args使用-execするファイルの数が6〜12倍になると、ファイルの数が増えるソリューションを使用すると効率が向上します。
1月Vlcinsky

3

これは、ワイルドカード式(*.jpg)が展開時にコマンドライン引数の長さの制限を超えるために発生します(おそらく、.jpgファイルが多数あるため/home/ftpuser/public_html/ftparea)。

findまたはを使用するなど、その制限を回避する方法がいくつかありますxargs。その方法の詳細については、この記事をご覧ください。


主題に関する優れた外部リソースに対して+1。
viam0Zah 2009年

3

GoldPseudoがコメントしたように、生成するプロセスに渡すことができる引数の数には制限があります。そのパラメーターの適切な説明については、彼の答えを参照してください。

プロセスに渡す引数が多すぎないようにするか、渡す引数の数を減らすことで、問題を回避できます。

シェル内のforループ、find、ls、grep、whileループはすべてこの状況で同じことを行います-

for file in /path/to/directory/*.jpg ; 
do
  rm "$file"
done

そして

find /path/to/directory/ -name '*.jpg' -exec rm  {} \;

そして

ls /path/to/directory/ | 
  grep "\.jpg$" | 
  while
    read file
  do
    rm "$file"
  done

すべてには、ディレクトリを読み取る1つのプログラム(シェル自体、find、およびls)と、実行ごとに実際に1つの引数を取り、コマンドのリスト全体を反復処理する別のプログラムがあります。

これで、*。jpgパターンに一致するファイルごとにrmをフォークして実行する必要があるため、これは遅くなります。

これがxargsの出番です。xargsは標準入力を取り、すべてのN(freebsdの場合はデフォルトで5000)行ごとに、N個の引数を持つ1つのプログラムを生成します。xargsは、上記のループの最適化です。コマンドラインから引数を読み取るファイルセット全体を反復処理するために、1 / Nプログラムをフォークするだけでよいためです。



1

「*」グロブは、非常に多くのファイル名に拡大しています。代わりにfind / home / ftpuser / public_html -name '* .jpg'を使用してください。


検索とエコー*の結果は同じ出力になります-ここで重要なのは、シェルがforkしようとしているコマンドに10億のコマンドライン引数をすべて渡すだけでなく、xargsを使用することです。
クリス

ファイルが多すぎるとecho *は失敗しますが、findは成功します。また、+を指定してfind -execを使用することは、xargsを使用することと同等です。(ただし、すべてがサポート+を見つけるわけではありません)
ウィリアムパーセル09

1

+オプションを使用するfind -execと、操作が大幅に高速化されます。

find  /home/ftpuser/public_html/ftparea/ -name "*jpg" -exec cp -uf -t /your/destination "{}" +

この+オプションは{}最後の引数である必要があるため、-t /your/destination(または--target-directory=/your/destination)オプションをcp使用して機能させます。

からman find

-execコマンド{} +

          This  variant  of the -exec action runs the specified command on  
          the selected files, but the command line is built  by  appending  
          each  selected file name at the end; the total number of invoca  
          tions of the command will  be  much  less  than  the  number  of  
          matched  files.   The command line is built in much the same way  
          that xargs builds its command lines.  Only one instance of  ‘{}’  
          is  allowed  within the command.  The command is executed in the  
          starting directory.

編集:cpの引数を再配置


私は見つけています: `-exec '/ home / ftpuser1 / public_html / ftparea /への引数がありません-name' * jpg '-exec cp -uf" {} "/ home / ftpuser2 / public_html / ftparea / +
icelizard

cpそのエラーを修正するために引数を再配置しました。
追って通知があるまで一時停止します。

1

*.jpgそのディレクトリにあるファイルが多すぎて、すべてを一度にコマンドラインに配置できないようです。あなたが試すことができます:

find /home/ftpuser/public_html/ftparea1 -name '*.jpg' | xargs -I {} cp -uf {} /home/ftpuser/public_html/ftparea2/

スイッチがシステムに適しているman xargsかどうかを確認するには、実装を確認する必要がある場合があり-Iます。

実際、これらのファイルを既に存在する同じ場所にコピーするつもりですか?


謝罪これらは2つの異なるディレクトリである必要がありますftpuser1とftpuser2
icelizard

ちょうどこれを試してみました:ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} / home / ftpuser2 / public_html / ftparea /まだ-bash:/ bin / ls:引数リストが長すぎる
icelizard 09

ああ、あなたはまったく正しい、もちろんls同じ問題を抱えているでしょう!私はfindどちらに変更しました。
グレッグヒューギル

0

フォルダーに移動

cd /home/ftpuser1/public_html/

そして、次を実行します。

cp -R ftparea/ /home/ftpuser2/public_html/

このように、フォルダ「ftparea」にサブフォルダがある場合、「*。jpg」ファイルのみが必要な場合、これは悪影響になる可能性がありますが、サブフォルダがなければ、このアプローチは間違いなくはるかに高速ですfindおよびxargsを使用する

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