並列性を使用して、多くのディレクトリをサブディレクトリに分割するか、このタスクを並列化します。

並列性を使用して、多くのディレクトリをサブディレクトリに分割するか、このタスクを並列化します。

parallel複数のディレクトリをサブディレクトリに並列に分割するために他のツールや方法を使用したいと思います。

たとえば、コンテンツが含まれているディレクトリが1,000,000個あるが、1つのディレクトリに入れるには多すぎるため、デフォルトディレクトリに10個のディレクトリを作成し、各ディレクトリから100,000個の元のディレクトリを移動しようとします。また、日付別のソートを使用したいと思います。私はすでに尋ねました。ここにも同様の質問がありますしかし、新しいコマンドを試して新しい結果を得たので、これは重複した質問ではありません。

だから私はこれを試しました。

ls -tr|parallel -n100000 mkdir "dir_{#}"\;mv {} "dir_{#}" 

この

ls -tr | parallel -j10 -n100000 --no-notice -k 'mkdir -p dir_{#}; mv {} -t dir_{#}' 

コマンドを実行しましたが、〜10 000万のサブディレクトリ(時には〜6200、時には〜12 500)に移動し、あまりにも多くのサブディレクトリを作成します(時には必要以上に10倍多い)。

私もこれを使ってみました。

ls -dtr * | parallel -j10 -n100000 --no-notice -k 'mkdir -p dir_{#}; mv {} -t dir_{#}'

しかし、それはbash: /bin/ls: Argument list too long

もちろん、各サブディレクトリに正確に100,000のディレクトリが必要ではありません。 101,000または98,500のディレクトリにすることができ、100,000の範囲の数字でなければなりません。

これを並列に実行するか、またはを使用してどのように実行できますかparallel

答え1

問題は、シェル拡張後にコマンドラインが占めるバイト数に上限があることです。この制限はシステムの制限によって異なります。

getconf ARG_MAX

mv {}したがって、最大制限に達する限り、入力ファイル名の長さによってパラメーターの数が異なります。

並列性の使用を放棄せずにこれらの制限を回避する解決策は、タスクを2つの段階に分けることです。

ls -tr | parallel -N 100000 --pipe -k "mkdir dir_{#}; parallel -X mv -t dir_{#}"

説明する

  • 最初のステップでは、オプションを使用して--pipe標準入力を決定された数に分割します。より小さい標準入力、各行にはオプションで指定されたn行が含まれています-N。この例を使用して効果を確認できます

    seq 1000000 | parallel -N 100000 --pipe wc -l
    

    100000で正確なセグメンテーションを提供します。

    100000
    100000
    100000
    ...
    
  • 第2段階では、内部並列が実行される。より小さい標準入力実行ジョブへの新しい標準入力として、この-Xオプションはコマンドラインの長さが許可するだけの数の引数を挿入します。

    mkdir dir_{#}; parallel -X mv -t dir_{#}
    

答え2

この問題には多くのIOが含まれます。parallelこの場合、これが実際に役に立つかどうか疑われます。

とにかく「伝統的な」アプローチを考えてみてください。

 mkdir dir_{1..10}
 ls -tr | nl | \
    awk '$2 !~ /^dir_/ {i=1+int($1/100000); print $2 | "xargs mv -t dir_"i}'

どこ

  • ls -tr | nl 日付でカタログを並べ替えて、セカンダリカタログ番号を追加します。
  • $2 !~ /^dir_/作成したばかりのフォルダをスキップするために使用されます。
  • i=1+int($1/100000)電話番号に基づいてフォルダ番号を計算する
  • print $2 | "xargs mv -t dir_"i移動には共正確算が不要

可能であれば、それぞれの時間も比較してみてください。 (time ....そして結果を私たちと共有してください☺)

関連情報