同じディレクトリで複数のmvコマンドを実行できますか(競争条件)?

同じディレクトリで複数のmvコマンドを実行できますか(競争条件)?

多数のファイル(400K +)をあるディレクトリから別のディレクトリに移動しており、これを行うための次のスクリプトがあります(mvコマンドが直接機能するにはファイルが多すぎます)。

for file in *;
do
    mv $file ..
done

このスクリプトを同時に2回(またはそれ以上)実行すると、mvコマンドが同じファイルにアクセスしようとしたときに競合状態が発生しますか?

オンラインで確認しましたが、明確な回答が見つかりませんでした。ありがとうございます!

答え1

競合状態が存在します(ただし問題ではありません)。

*ループに入るときに展開します。このスクリプトの2番目のインスタンスを同時に実行すると、移動しようとしているすべてのファイルがすでに移動されているため、何もしない可能性があります。移動操作中にソースディレクトリにファイルが生成されなかった場合、エラーメッセージは最大の問題です。

しかし、全体的にこの構造は非常に悪い考えです。*ソートされたリストに展開します。 AFAIKを無効にすることはできません。明らかに400Kファイルの場合、ソートするだけでも悪夢です。man bash「パス名の拡張」セクションを参照してください。

単語分割後のbashは、-fオプションが設定されていない限り、各単語で*、?と[文字を検索します。これらの文字のいずれかが発生すると、その単語はパターンとして扱われ、パターンと一致するファイル名のアルファベット順のリストに置き換えられます。

mvまた、一度に複数のファイルを移動できるため、ファイルごとに1つのインスタンスを実行しないでください。

GNUの世界でより良い解決策は次のとおりです。

find . -mindepth 1 -maxdepth 1 -exec mv --target-directory=DIRECTORY {} +

答え2

より良い解決策は、次を使用することです。GNUパラレル到着複数パラメータの挿入。デフォルトでは、Parallelはジョブnを同時に実行し、nその数はCPUのコア数です。

次のように多数のファイルを移動すると、次mv * destdirのエラーが発生することがあります。

bash: /bin/mv: Argument list too long

ファイルが多すぎるからです。次のことができます。

ls -1 | parallel mv {} destdir

これはmv各ファイルに対して実行されます。 mvが次の行に一致するだけの引数を取ると、より速く実行できます。

ls -1 | parallel -m mv {} destdir


オプション-mは次のとおりです。本物ファイルを並列に移動またはコピーすることをお勧めします。

-m      Multiple arguments. Insert as many arguments as the command
        line length permits. If multiple jobs are being run in
        parallel: distribute the arguments evenly among the jobs.
        Use -j1 to avoid this.

答え3

私のようにparallel手に入らない人のために

find source_dir -type f | xargs -n 1 -P 20 -I '{}' mv '{}' dest_dir/

-Ponパラメータを使用してプロセス数を定義できますxargs(上記の例では20に設定)。

関連情報