自动复制文件夹,直到达到某个限制

时间:2008-12-27 21:25:11

标签: directory copying

问候。

1 - 假设我有大约500个可变大小的文件夹,总大小为100 GB。

2 - 我希望在其他文件夹中自动分发这些文件夹,直到达到700 MB的大小并获得最佳的空间优化。

示例:在“CD-01”文件夹中,我想在不通过700 MB限制的情况下获得最大文件夹数,依此类推“CD-02”,“CD-03”..

是否有工具允许我“动态”执行此操作,还是我必须自己编写代码?

由于

5 个答案:

答案 0 :(得分:2)

最终,您要求找到Knapsack Problem in many forms的解决方案。

一种简单的方法是按照以下伪代码,但这将为所有输入生成最佳解决方案(参见上面的文章)。

while (there are unallocated files) {
    create a new, empty directory
    set remaining space to 700,000,000
    while (the size of the smallest unallocated is at most (<=) the remaining space) {
        copy into the current the largest unallocated file with size at most the remaining space
        subtract that file's size from the remaining space
        remove that file from the set of unallocated files
    }
    burn the current directory
}

(当然,这假设没有单个文件大小超过700MB。如果可能,请务必从未分配的列表中删除任何此类文件,否则上面会生成无限多个空目录!;-)

答案 1 :(得分:0)

如果您使用的是UNIX(包括Mac OSX),则可以编写类似

的脚本
tar cvzf allfolders.tgz ./allfolders
split allfolders.tgz -b 700m

这将创建所有文件夹的(压缩)存档,然后将其拆分为700M大小的块。但是,当您想重新构建原始文件夹集时,您需要重新组合所有碎片然后再使用tar提取。

如果你想将它们作为单独的OS文件夹保存在CD上,那就相当困难了(事实上我认为这是一种背包问题,这是NP难的)。

答案 2 :(得分:0)

有一些工具可以做到这一点 - 类似于frankodwyer的回答,WinZip将你的100GB,拉链并将其拆分成你想要的任何大小的“块” - 即〜700MB

这是the page the WinZip split feature

答案 3 :(得分:0)

这是一个非常天真且编码不佳的解决方案,但它确实有效。我的bash-fu并不强大,但shell脚本似乎是解决这个问题的最好方法。

#!/bin/bash
dirnum=1
for i in *
    do
    if [ `du -b -s "$i" | cut -f 1` -gt 700000000 ]
        then
        echo "$i is too big for a single folder, skipping"
        continue
    fi
    if [ ! -d "CD_$dirnum" ]
        then
        echo "creating directory CD_$dirnum"
        mkdir "CD_$dirnum"
    fi
    echo "moving $i to CD_$dirnum"
    mv "$i" "CD_$dirnum"
    if [ `du -b -s "CD_$dirnum" | cut -f 1` -gt 700000000 ]
        then
        echo "CD_$dirnum is too big now"
        mv "CD_$dirnum/$i" .
        let "dirnum += 1"
        if [ ! -d "CD_$dirnum" ]
            then
            echo "creating directory CD_$dirnum"
            mkdir "CD_$dirnum"
        fi
        echo "moving $i to CD_$dirnum"
        mv "$i" "CD_$dirnum"
    fi
done

答案 4 :(得分:0)

我参加聚会有点晚了,但这是我解决问题的方法:

#!/usr/bin/env bash

sourcedir="$1"
destdir_prefix="./disk_"
destdir_suffix=""
mblimit=4100
# bytelimit=$(( mblimit * 1024 * 1024 )) # MB as measured by OS (MiB)
bytelimit=$(( mblimit * 1000 * 1000 )) # MB as measured by marketeers
disk=() # empty array
dir_size=0
find "${sourcedir}" -type f |
  while read file; do

    file_size="$( stat --printf="%s" "${file}" )"
    disk_number=0
    stored=false
    while [[ "${stored}" == "false" ]]; do

      if [[ "${disk[$disk_number]}" == "" ]]; then
        disk[$disk_number]=0
      fi

      if [[ $(( disk[disk_number] + file_size )) -lt ${bytelimit} ]]; then
        dir="${destdir_prefix}${disk_number}${destdir_suffix}"
        mkdir -p "${dir}"
        filedir="$(echo ${file} | sed 's|[^/]*$||g')"
        mkdir -p "${dir}/${filedir}"
        disk[$disk_number]=$(( disk[disk_number] + file_size ))
        echo "${disk[$disk_number]} ${dir}/${file}"
        cp "${file}" "${dir}/${file}"
        stored=true
      else
        disk_number=$(( disk_number + 1 ))
      fi
    done
  done

这将创建名为disk_0,disk_1等的文件夹。对于每个文件,它将尝试将文件放入disk_0,如果不合适,则将尝试disk_1,等等。