Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash一次将500个目录从总共160000个目录移动到子目录_Bash_Shell_Amazon S3 - Fatal编程技术网

bash一次将500个目录从总共160000个目录移动到子目录

bash一次将500个目录从总共160000个目录移动到子目录,bash,shell,amazon-s3,Bash,Shell,Amazon S3,出于各种原因,我需要将一个大型s3存储区移动到本地文件存储区,这些文件被存储为160000个带有子目录的目录 由于这个文件夹太多,无法使用gui FTP界面查看,因此我想将160000个根目录移动到320个目录中,每个目录中有500个目录 我是bash脚本的新手,我刚刚写了这篇文章,但我害怕我会把整个事情搞砸,不得不重做传输。我用[[“$I”-ge 3]]测试;还有一些带有子目录的目录,看起来效果不错,但我很紧张。不想重新传输所有这些数据 i=0; j=0; for file in *; do

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

由于这个文件夹太多,无法使用gui FTP界面查看,因此我想将160000个根目录移动到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
谢谢你的帮助

  • 查找当前文件夹中的所有目录
  • 读取文件夹的计数
  • 为每个区块执行
    mv


一种可能的方法是,但您无法控制计数器:

find . -type d -mindepth 1 -maxdepth 1 -print0 \
   | xargs -0 -n 500 sh -c 'echo mkdir -v ./assets_$$ && echo mv -v "$@" ./assets_$$' _
这将从PID中获取
资产的计数器,该PID仅在达到环绕时循环()

find
返回的顺序与glob
*
()

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

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

注意:如果您对输出感到满意,则在工作目录中尚不存在资产1、资产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
dirs=(./*/)

为了((i=0,j=1;i你的问题不是很清楚。你能举个例子说明你想要什么吗,比如说10个Directories可能很有用。如果我是你,我会创建一个包含要移动的文件夹列表的文件,然后我会遍历该文件,并在另一个文件中记录所做的工作。你可以用cp代替cpmv.如果出现问题,您可以重新启动它。在这种情况下,cp应该不会太慢(除了当您有一个好的本地副本时您可能需要rm*之外),您可能应该添加一个
[[$file=assets_*]]&&continue
在循环的顶部,这样您就不会试图重命名已经存在的
资产*
目录。顺便说一句,
如果((i>=499))
是比较
i
499
的更好的bashism。如果您要使用不符合POSIX的语法,最好选择可读性更强的专用语法。:)我建议
printf'%q'mv'${dirs[@]:i:50}/assets_$j/;echo
——它现在的做法将歪曲使用带有空格/globs/等的名称实际运行的内容(可能会在
mkdir
中添加一个
-p
,这样当目录已经存在时它就不会抱怨了……好吧,要么这样,要么循环递增
j
,直到我们得到一个不存在的目录).@Charles你说得对,但这会让你感到困惑OP@Charles如果目录已经存在,这将造成混乱。我也不是说你错了——答案有我的赞成票;我只是在开玩笑,我就是这么做的。:)
dirs=(./*/)
for (( i=0,j=1; i<${#dirs[@]}; i+=500,j++ )); do
    echo mkdir ./assets_$j/ 
    echo mv "${dirs[@]:i:500}" ./assets_$j/
done