web-dev-qa-db-ja.com

フォルダー内の一部のファイルの移動に、フォルダー全体の移動よりも時間がかかるのはなぜですか?

Ubuntuクラウドサーバーには数百万の画像があります。 mvコマンドを使用して、1200万枚の画像を含む完全なフォルダーを移動すると、ほぼ瞬時に移動します。ただし、mv画像のみ(フォルダーではない)の場合は、時間がかかります。すべての画像をフォルダと同じ速さで移動する方法はありますか?

これは何が起こっているかです:

  1. srcフォルダーには1200万の画像があり、これを使用してdstフォルダーに移動します

    $ mv  src ../dst
    

    すぐに起こる

  2. Srcフォルダー内でこれを実行して移動します。

    find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
    

    これには時間がかかります。

2番目のプロセスをスピードアップする方法はありますか?

21
sankit

TL; DR:いいえ

ファイルの量が少ない場合、findは必要ありませんが、この単純化された小さい場合でも、

mv *.jpg ../../dst/

ディレクトリ全体を一度に移動するよりも時間がかかります。


なぜ?ポイントは、mvが何をするかを理解することです。

簡単に言えば、mvは(ディレクトリまたはファイルを識別する)番号をiノード(それを含むディレクトリ)から別のiノードに移動し、これらのインデックスはファイルシステムのジャーナルまたはFATで更新されます(ファイルシステムがそのような方法で実装されている場合)。

コピー元とコピー先が同じファイルシステム上にある場合、データの実際の移動はなく、それらが接続されている位置を変更するだけです。

したがって、mvoneディレクトリの場合、この操作を実行していますone time

ただし、100万ファイルを移動すると、この操作100万回を実行します。

実用的な例を挙げると、多くの枝を持つツリーがあります。特に、100万のブランチが接続されている1つのノードがあります。
これらの枝を切り倒して他の場所に移動するには、それぞれを100万カットするか、ノードの直前でカットして、1つだけカットします(これが違いです)ファイルとディレクトリの移動の間)。

50
dadexix86

前述のように、ファイルシステムは各ファイル名を新しい場所に再リンクする必要があるため、依然として低速です。

ただし、現在の状態からスピードアップできます。

Findコマンドは、ファイルごとに1回execを実行します。そのため、1200万のファイルに対してmvコマンドを1200万回起動します。これは2つの方法で改善できます。

  • 最後にプラスを追加します。
    find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
    マンページをチェックして、findのバージョンでサポートされていることを確認してください。効果は、各コマンドラインに収まるだけのファイル名で一連のmvコマンドを実行することです。

  • findxargsを一緒に使用します。
    find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
    -print0はNUL(別名ゼロバイト)を使用してファイル名を区切ります。これに加えてxargs -0は、ファイル名にスペースが含まれない場合にxargsが持つ問題を修正します。 xargsコマンドは、findコマンドからファイル名のリストを読み取り、適切な数のファイル名でmvコマンドを実行します。

13
Zan Lynx

混乱は、ファイルシステムの抽象化から生じます。この抽象化により、フォルダにはファイルや他のフォルダがツリー状に含まれていると思われます。これは実際には正しくありません。ファイルシステム内のすべてのファイルとディレクトリは同じレベルにあり、実装に応じて何らかの番号で識別されます。ディレクトリは、他のファイルのリストを含む特別なファイルです。

ファイルシステム内でファイルを「移動」すると、実際のファイルはどこにも移動しません。むしろ、ディレクトリ内のリストは変更を反映するために更新されます。

mv src ../dstは、単一のリストエントリをディレクトリ.からディレクトリ../dstに移動するため、高速です。

find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/は何百万ものエントリを移動する必要があるため、処理が遅くなります。 mvをファイルごとに1回だけ呼び出し、1回だけではなくmvコマンド自体を最適化して、複数のディレクトリエントリを1ステップで移動する場合、速度が向上する可能性がありますが、単一のディレクトリを移動するときと同じ速さです。

7

簡単な答え

ファイルの移動は3つのステップで完了します。

  • ファイルへのリンクを宛先フォルダーのiノードリストに追加します
  • リンクが正常に追加されたかどうかを確認します
  • 上記のチェックが成功した場合、ソースフォルダーのiノードのリストからリンクを削除します。

このプロセスは、ファイルまたはフォルダーの場合と同じです。
[。

man linkはadd()です
man unlinkはremove()です
mvは、上記の2つのコマンドを使用し、その間のチェックを追加してデータの損失を防ぎます。

4
user257256