将文件重新分配到具有最大大小的多个子目录中

时间:2019-05-09 08:34:56

标签: bash bin-packing

我有一个大型目录printf(),其中包含11万个pdf文档。这些文档中的每一个都有不同的文件大小。

我想将所有这些文档重新分配到一组子目录中,以使所有子目录的总累积大小大约。我不想将文件分成多个部分。

我尝试过:

files_pdf

但是在某些情况下会破坏我的PDF。

1 个答案:

答案 0 :(得分:2)

基于bin-packing First-fit算法的解决方案可能如下。

创建一个名为bin_packing.awk的文件:

function first_fit(v, file) {
    # find first bin that can accomodate the volume
    for (i=1; i<=n; ++i) {
        if (b[i] > v) {
            b[i] -= v
            bc[i]++
            cmd="mv "file" subdir_" i
            print cmd
            # system(cmd)
            return
        }
    }
    # no bin found, create new bin
    if (i > n) {
        b[++n] = c - v
        bc[n]++
        cmd="mkdir subdir_"n
        print cmd
        # system(cmd)
        cmd="mv "file" subdir_"n
        print cmd
        # system(cmd)
    }
    return
}
BEGIN{ if( (c+0) == 0) exit }
{ first_fit($1,$2) }
END { print "REPORT:"
    print "Created",n,"directories"
    for(i=1;i<=n;++i) print "- subdir_"i,":", c-b[i],"bytes",bc[i],"files"
}

然后执行以下行:

$ find . -type f -iname '*pdf' -printf "%s %p\n"

这将创建一个文件列表,其前面的文件大小为字节。类似于:

8 file_1
1 file_2
8 file_3
4 file_4
4 file_5
4 file_6
10 file_7
...

现在您可以运行以下命令:

$ find . -type f -iname '*pdf' -printf "%s %p\n" \
  | awk -v c=100000 -f bin_packing.awk

在上一行中,将值c设置为目录可以以字节为单位的最大大小。上面的值c=100000仅是一个例子。

这将创建如下输出:

...
mv file_47 subdir_6
mv file_48 subdir_6
mv file_49 subdir_5
mv file_50 subdir_6
REPORT:
Created 6 directories
- subdir_1 : 49 bytes 12 files
- subdir_2 : 49 bytes 9 files
- subdir_3 : 49 bytes 8 files
- subdir_4 : 49 bytes 8 files
- subdir_5 : 48 bytes 8 files
- subdir_6 : 37 bytes 5 files

如果您喜欢所看到的内容,则可以考虑删除bin_packing.awk脚本中的注释。

注意:这清楚地假设您的文件名是正常的。即没有有趣的人物,而且中间没有空格。