test という名前のフォルダーがあり、その中には jpeg ファイルのみが含まれています。ファイルの数は数千です。1.jpg、2.jpg... 345623.jpg などの名前の付いたこれらの数千のファイルを、それぞれ 1000 個のファイルを含む 001000、002000 などの名前のサブフォルダーに配置する必要があります。したがって、最もパフォーマンスの高い効率的な方法で、test フォルダーからすべての jpg ファイルを、それぞれ 1000 個の jpg ファイルを含むサブフォルダーに移動する必要があります。
これまでに私が持っているものは次のとおりです。
i=1;while read l;do mkdir $i;mv $l $((i++));done< <(ls|xargs -n1000)
答え1
find . -type f \
| split -l 1000 -a 3 --numeric-suffixes=1 \
--filter='target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"' \
- ''
説明:
find . -type f
ファイルを検索します (サブディレクトリ内でも検索されますが、あなたのケースではまだサブディレクトリは存在しないと思います)。split -l 1000 -a 3 --numeric-suffixes=1 ... - ''
は、stdin (-
) からデータを読み取り、各チャンクの長さが 1000 行 ( ) のチャンクに分割します。各チャンクには、空のプレフィックス ( ) と、長さが 3 ( ) の1 から始まる数値サフィックス( )-l 1000
で構成される「名前」が関連付けられます。この時点では、名前は、などとなります。''
--numeric-suffixes=1
-a 3
001
002
--filter=...
指定されたコマンドを各チャンクごとに個別に実行します。それぞれの名前は として利用できます$FILE
。実行するコマンドはtarget="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"
target="${FILE}000"
001
またはのような名前を、002
必要な将来のディレクトリ名 (001000
または002000
など) に変換し、これをtarget
変数に格納します。mkdir "$target"
希望する名前で新しいディレクトリを作成します。xargs -d "\n" ...
チャンク全体 (1000 個のファイルパス、または最後のチャンクではそれ以下) を読み取り、各行全体 (区切り文字として改行:-d "\n"
) を後続のコマンドの引数として使用します。mv -t "$target"
オブジェクト ( によって渡されたxargs
) を新しく作成されたディレクトリに移動します。
ノート:
- このコマンドはファイル名を気にしません。
345623.jpg
は必ずしも になるわけではありません346000/
。考えられる理由:find
はソートされませんが、とsort -n
の間にを入れても、次のようになる場合があります...find
split
- 番号にギャップがあります。
split
どのような場合でも 1000 エントリを取得します (最後のチャンクの場合は 1000 以下)。
mkdir ... && xargs ...
xargs
失敗した場合は実行されませんmkdir
(既存のディレクトリに注意してください)。cp -l -t "$target"
の代わりにを使用するmv -t "$target"
と、ディレクトリにハードリンクが作成され、現在のディレクトリの既存のエントリはそのまま残ります。この方法では、何か問題が発生した場合に、rm -r
ディレクトリだけを削除して新たに開始します。 を使用するmv
と、タスクが中断された場合、一部のファイルは移動され、一部のファイルは移動されないため、混乱が生じる可能性があります。- (末尾にゼロを追加した後)では、
-a 3
通過できないと思います。さらにチャンクを作成する必要がある場合、ジョブの途中で失敗します。このため、コマンドを実行する前に十分であることを確認してください。999
999000
split
999
- 改行を含む名前はコードを壊します (一般に、ファイル名は問題ないように見えます)。