我有一个名为 test 的文件夹,里面只有 jpeg 文件。数千个文件。我需要将这些数千个文件(命名为 1.jpg、2.jpg...345623.jpg)放入子文件夹中,这些子文件夹的名称将类似于 001000、002000,每个子文件夹包含 1000 个文件。因此,我需要以最高效的方式将所有 jpg 文件从 test 文件夹移动到包含每个 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 ... - ''
从其标准输入 (-
) 读取数据,并将数据拆分为块,每块长 1000 行 (-l 1000
)。每个块都有一个关联的“名称”,由空前缀 (''
) 和数字后缀组成,从 1 ( ) 开始,--numeric-suffixes=1
长度为 3 (-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
在运行命令之前请确保足够。 - 带有换行符的名称会破坏代码(一般来说,您的文件名看起来不错)。