Ubuntuクラウドサーバーには数百万の画像があります。 mv
コマンドを使用して、1200万枚の画像を含む完全なフォルダーを移動すると、ほぼ瞬時に移動します。ただし、mv
画像のみ(フォルダーではない)の場合は、時間がかかります。すべての画像をフォルダと同じ速さで移動する方法はありますか?
これは何が起こっているかです:
srcフォルダーには1200万の画像があり、これを使用してdstフォルダーに移動します
$ mv src ../dst
すぐに起こる
Srcフォルダー内でこれを実行して移動します。
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
これには時間がかかります。
2番目のプロセスをスピードアップする方法はありますか?
TL; DR:いいえ
ファイルの量が少ない場合、find
は必要ありませんが、この単純化された小さい場合でも、
mv *.jpg ../../dst/
ディレクトリ全体を一度に移動するよりも時間がかかります。
なぜ?ポイントは、mv
が何をするかを理解することです。
簡単に言えば、mv
は(ディレクトリまたはファイルを識別する)番号をiノード(それを含むディレクトリ)から別のiノードに移動し、これらのインデックスはファイルシステムのジャーナルまたはFATで更新されます(ファイルシステムがそのような方法で実装されている場合)。
コピー元とコピー先が同じファイルシステム上にある場合、データの実際の移動はなく、それらが接続されている位置を変更するだけです。
したがって、mv
oneディレクトリの場合、この操作を実行していますone time。
ただし、100万ファイルを移動すると、この操作100万回を実行します。
実用的な例を挙げると、多くの枝を持つツリーがあります。特に、100万のブランチが接続されている1つのノードがあります。
これらの枝を切り倒して他の場所に移動するには、それぞれを100万カットするか、ノードの直前でカットして、1つだけカットします(これが違いです)ファイルとディレクトリの移動の間)。
前述のように、ファイルシステムは各ファイル名を新しい場所に再リンクする必要があるため、依然として低速です。
ただし、現在の状態からスピードアップできます。
Findコマンドは、ファイルごとに1回execを実行します。そのため、1200万のファイルに対してmv
コマンドを1200万回起動します。これは2つの方法で改善できます。
最後にプラスを追加します。find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
マンページをチェックして、find
のバージョンでサポートされていることを確認してください。効果は、各コマンドラインに収まるだけのファイル名で一連のmv
コマンドを実行することです。
find
とxargs
を一緒に使用します。find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
-print0
はNUL(別名ゼロバイト)を使用してファイル名を区切ります。これに加えてxargs -0
は、ファイル名にスペースが含まれない場合にxargs
が持つ問題を修正します。 xargs
コマンドは、find
コマンドからファイル名のリストを読み取り、適切な数のファイル名でmv
コマンドを実行します。
混乱は、ファイルシステムの抽象化から生じます。この抽象化により、フォルダにはファイルや他のフォルダがツリー状に含まれていると思われます。これは実際には正しくありません。ファイルシステム内のすべてのファイルとディレクトリは同じレベルにあり、実装に応じて何らかの番号で識別されます。ディレクトリは、他のファイルのリストを含む特別なファイルです。
ファイルシステム内でファイルを「移動」すると、実際のファイルはどこにも移動しません。むしろ、ディレクトリ内のリストは変更を反映するために更新されます。
mv src ../dst
は、単一のリストエントリをディレクトリ.
からディレクトリ../dst
に移動するため、高速です。
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/
は何百万ものエントリを移動する必要があるため、処理が遅くなります。 mv
をファイルごとに1回だけ呼び出し、1回だけではなくmv
コマンド自体を最適化して、複数のディレクトリエントリを1ステップで移動する場合、速度が向上する可能性がありますが、単一のディレクトリを移動するときと同じ速さです。
簡単な答え
ファイルの移動は3つのステップで完了します。
このプロセスは、ファイルまたはフォルダーの場合と同じです。
[。
man link
はadd()ですman unlink
はremove()ですmv
は、上記の2つのコマンドを使用し、その間のチェックを追加してデータの損失を防ぎます。