如何将目录的所有文件移动到具有给定数量文件的多个目录中?

ces*_*rch 6 bash shell

我有一个包含超过27000个图像的目录.

我想将这些文件拆分成每个包含大约500个图像的文件夹.

它们如何排序并不重要,我只想将它们分开.

Sor*_*rin 9

一个"简单"的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分隔文件(以处理奇怪的名称)
  • xargs的
    • -r 不要运行空参数列表
    • -0 读取以null分隔的文件
    • -P0 根据需要创建任意数量的流程
    • -n 500 使用500个参数运行每个进程
  • SH
    • -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 排序文件


Pet*_*esh 6

以下应该有效:

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)