一个"简单"的find/xargs会:
find -maxdepth 1 -type f -print0 | xargs -r -0 -P0 -n 500 sh -c 'mkdir newdir.$$; mv "$@" newdir.$$/' xx
Run Code Online (Sandbox Code Playgroud)
说明:
-maxdepth 1 防止查找以递归方式遍历任何目录,安全,如果您知道没有目录则不需要-type f 只找到文件 -print0 使用null char而不是LF分隔文件(以处理奇怪的名称)-r 不要运行空参数列表-0 读取以null分隔的文件 -P0 根据需要创建任意数量的流程-n 500 使用500个参数运行每个进程 -c 运行命令行脚本作为下一个参数提供mkdir newdir.$$ 创建一个以shell进程PID结尾的新目录 mv "$@" newdir.$$/ 将脚本的参数(每个引用它们)移动到新创建的目录中xx 命令行提供脚本的名称(参见sh手册)请注意,这不是我在生产中使用的东西,它主要基于以下事实:$$(pid)对于xargs执行的每个进程都是不同的
如果你需要排序的文件,你可以在sort -z之间找到一个xargs.
如果你想要更有意义的目录名,你可以使用这样的东西:
echo 1 >../seq
find -maxdepth 1 -type f -print0 |sort -z | xargs -r -0 -P1 -n 500 sh -c 'read NR <../seq; mkdir newdir.$NR; mv "$@" newdir.$NR/; expr $NR + 1 >../seq' xx
Run Code Online (Sandbox Code Playgroud)
echo 1 > ../seq 在文件中写入第一个目录后缀(确保它不在当前目录中)-P1 告诉xargs一次运行一个命令以防止竞争条件 read NR <../seq 从文件中读取当前目录后缀 expr $NR + 1 >../seq 为下一次运行写下一个目录后缀 sort -z 排序文件以下应该有效:
dest_base="destination"
src_dir="src/"
filesperdir=500
atfile=0
atdir=0
for file in $src_dir/*; do
if ((atfile == 0)); then
dest_dir=$(printf "$dest_base/%0.5d" $atdir)
[[ -d $dest_dir ]] || mkdir -p $dest_dir
fi
mv $file $dest_dir
((atfile++))
if ((atfile >= filesperdir)); then
atfile=0
((atdir++))
fi
done
Run Code Online (Sandbox Code Playgroud)