【问题标题】:Automatically Copying folders until a certain limit is reached自动复制文件夹,直到达到特定限制
【发布时间】:2010-09-28 13:37:50
【问题描述】:

您好。

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

2 - 我想将这些文件夹自动分配到其他文件夹中,直到达到 700 MB 的大小并优化空间。

示例:在文件夹“CD--01”中,我希望在不超过 700 MB 限制的情况下拥有尽可能多的文件夹,依此类推,在“CD--02”、“CD--03”中。 .

是否有一种工具可以让我“即时”执行此操作,还是我必须自己编写代码?

谢谢

【问题讨论】:

  • 最好地做到这一点是背包问题。无法在合理的时间内解决任何重要的数据集。非最优是可行的。
  • 不,不是,文件没有价值。这有很大的不同。

标签: directory copying


【解决方案1】:

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

#!/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等。

【讨论】:

    【解决方案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。如果可能,请务必从未分配列表中删除任何此类文件,否则上述将产生无限多的空目录!;-)

    【讨论】:

      【解决方案3】:

      这是一个非常幼稚且编码不佳的解决方案,但它确实有效。我的 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
      

      【讨论】:

      • 谢谢 Sparr.... 我不在 UNIX 下.... 但我总是可以在 Win 和 Unix 虚拟机之间共享一个文件夹并运行该脚本。我试试看。
      • bash 可通过 cygwin 在 Windows 上使用,但必须考虑诸如驱动器号和 \ 与 / 之类的问题
      • 另外,正如 joel.neely 的回答所指出的那样,一个明显的改进是寻找更小的东西来移动到一个几乎完整的目录中,而不是在下一个项目成功后立即创建一个新的t 适合当前的 ont。
      【解决方案4】:

      有一些工具可以做到这一点 - 类似于 frankodwyer 的回答,WinZip 将占用您的 100GB,将其压缩并拆分为您想要的任何大小的“块” - 即 ~700MB

      这里是the page the WinZip split feature

      【讨论】:

        【解决方案5】:

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

        tar cvzf allfolders.tgz ./allfolders
        split allfolders.tgz -b 700m
        

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

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

        【讨论】:

          猜你喜欢
          • 2018-05-17
          • 2020-08-03
          • 1970-01-01
          • 2016-06-26
          • 2021-05-13
          • 1970-01-01
          • 2018-12-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多