【问题标题】:bash move 500 directories at a time to subdirectory from a total of 160,000 directoriesbash 一次将 500 个目录从总共 160,000 个目录移动到子目录
【发布时间】:2020-06-30 16:39:51
【问题描述】:

出于各种原因,我需要将一个大型 s3 存储桶移动到本地文件存储中,这些文件存储为 160,000 个带有子目录的目录。

由于文件夹太多,无法使用 gui FTP 界面之类的东西查看,我想将 160,000 个根目录移动到 320 个目录中,每个目录 500 个目录。

我是 bash 脚本的新手,我刚刚写了这篇文章,但我害怕我会搞砸整个事情并且不得不重做转移。我用 [[ "$i" -ge 3 ]];和一些带有子目录的目录,看起来它工作正常,但我很紧张。不想重新传输所有这些数据。

i=0;
j=0;

for file in *; do
  if [[ -d "$file" && ! -L "$file" ]];
    then
      ((i++))
      echo "directory $file is being written to assets_$j";
      mv $file ./assets_$j/;
      if [[ "$i" -ge 499 ]];
        then
          ((j++));
          ((i=0));
      fi
  fi;
done

感谢您的帮助!

【问题讨论】:

  • 你的问题不是很清楚。你能举一个你想要的例子吗,比如说 10 个目录
  • 也许rsync 有用。如果我是你,我会创建一个包含要移动的文件夹列表的文件,然后我会遍历该文件并在另一个文件中记录已完成的工作。
  • 你可以用 cp 代替 mv。然后,如果出现问题,您可以重新启动它。在这种情况下, cp 应该不会慢很多(除了你可能想要 rm * 当你有一个好的本地副本时)
  • 您可能应该在循环顶部添加一个[[ $file = assets_* ]] && continue,这样您就不会尝试重命名已经存在的assets_* 目录。
  • 顺便说一句,if (( i >= 499 )) 是比较 i499 的更好的 bashism。如果您要使用不符合 POSIX 的语法,不妨选择更具可读性、内置目的的语法。 :)

标签: bash shell amazon-s3


【解决方案1】:
  • find当前文件夹下的所有目录。
  • 读取文件夹计数。
  • 为每个块执行mv

find . -mindepth 1 -maxdepth 1 -type d |
while IFS= readarray -n10 -t files && ((${#files[@]})); do
     dest="./assets_$((j++))/"
     echo mkdir -v -p "$dest"
     echo mv -v "${files[@]}" "$dest";
done

【讨论】:

    【解决方案2】:

    在assets_1、assets_2等不存在于工作目录的情况下:

    dirs=(./*/)
    for (( i=0,j=1; i<${#dirs[@]}; i+=500,j++ )); do
        echo mkdir ./assets_$j/ 
        echo mv "${dirs[@]:i:500}" ./assets_$j/
    done
    

    如果您对输出感到满意,请删除 echos。

    【讨论】:

    • 我建议printf '%q ' mv "${dirs[@]:i:50}" ./assets_$j/; echo——现在的做法会歪曲实际运行的内容,名称为空格/globs/等。
    • (并且可能在mkdir 中添加一个-p,这样当目录已经存在时它就不会抱怨......好吧,要么循环增加j,直到我们得到一个不存在的目录)。
    • @Charles 你是对的,但这会让 OP 感到困惑
    • @Charles 如果目录已经存在,这会弄得一团糟。
    • 我也不是说你错了——答案是我赞成的;只是kibitzing,这就是我所做的。 :)
    【解决方案3】:

    一种可能的方法是:

    find . -type d -mindepth 1 -maxdepth 1 -print0 \
       | xargs -0 -n 500 sh -c 'echo mkdir -v ./assets_$$ && echo mv -v "$@" ./assets_$$' _
    

    这会从 PID 中获取 assets 的计数器,该计数器仅在达到回绕时回收 (Linux PID recycling)

    findreturns 的顺序与全局 * (Find command default sorting order) 略有不同

    如果你想按字母顺序排列,你可以添加一个简单的排序:

    find . -type d -mindepth 1 -maxdepth 1 -print0 | sort -z \
       | xargs -0 -n 500 sh -c 'echo mkdir -v ./assets_$$ && echo mv -v "$@" ./assets_$$' _
    

    注意:如果您对输出感到满意,请移除回声

    【讨论】:

      猜你喜欢
      • 2020-05-01
      • 2023-04-07
      • 2020-01-07
      • 1970-01-01
      • 2016-06-09
      • 2017-07-20
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多