使用 shell 脚本按给定顺序对随机范围目录进行分组的脚本

使用 shell 脚本按给定顺序对随机范围目录进行分组的脚本

1)我有从0到3120203的目录(注意目录不是按顺序排列的,它们是随机的)

-bash-4.1$ ls
0        1261826  211205   2398339  267475   295482   339902  395546  457254  503959  538784  583032  643106  78093   906653
1000791  126359   211250   2398362  267592   295488   340070  39565   457378  504052  538846  583103  643168  78143   91594
1001022  126944   2114355  2398373  267667   29583    341088  395652  457471  504160  540470  583316  64447   781579  91777
1002557  127163   2129010  2398380  267771   2959608  341300  395786  457628  504219  540632  583875  645373  782220  921760
1004183  127316   2129165  2398388  268076   296331   341452  396207  457758  504278  541300  583998  645437  78227   924976
1004399  127416   2132965  2398396  2681923  296456   341512  39720   457820  504337  541754  584219  645816  782272  925382
1005369  130416   2137199  2398482  268333   2964801  341688  39779   457879  504404  541994  584278  645876  782704  928134

2)我想对所有这些目录进行排序和分组,并将其移动到 50000 的特定范围内。

例如:从 0 到 50000 的目录应移到 50000 下,50001 到 100000 的目录应移到 100000 下,依此类推。迭代次数应为 50000

我不是 shell 脚本专家:

这是我的 shell 脚本:

#!/bin/bash
#set -x
#Please pass document library path
SOURCE=/opt/dms/
DEST=/opt/nes_dms
cd $SOURCE
ls | sort -n >> /opt/ncm/list.txt
for dir in `cat /opt/ncm/list.txt`
do
#echo $dir
if [ "$dir" -le "50000" ]
then
echo $dir is less then $i
mv $dir $DEST
fi
done

我需要脚本自动递增 50000+50000=100000,并将 100000 目录中 50001 到 100000 之间的所有目录移动,直到我们读取文件中的所有目录。

答案1

#!/bin/bash
#set -x
#Please pass document library path
SOURCE='/crypto/home/hl/tmp/stackexchange/dir_groups/source'
DEST='/crypto/home/hl/tmp/stackexchange/dir_groups/target'
declare -a target_dir_indexes
cd "$SOURCE" || exit 1
for dir in *; do
    test "$DEBUG" = 'yes' && echo "$dir"
    test -d "$dir" && ! test -L "$dir" || continue
    if ! [[ "$dir" =~ ^(0|[1-9][0-9]*)$ ]]; then
        echo "error: dir name '${dir}'; skipping"
        continue
    fi
    target_index=$((dir/50000))
    if [ "$dir" -gt 0 ]; then
        if [ $((dir%50000)) -eq 0 ]; then
            ((target_index--))
        fi
    fi
    target_dir_name=$(((target_index+1)*50000))
    target_dir_path="${DEST}/${target_dir_name}"
    # avoid unneccessary calls to mkdir or the VFS
    if [ -z "${target_dir_indexes[target_index]}" ]; then
        mkdir -p "$target_dir_path"
        target_dir_indexes[target_index]=1
    fi
    echo "${dir} is moved to ${target_dir_name}"
    mv -i "$dir" "$target_dir_path"
done

答案2

数学有点棘手。简单的整数除法(file/50000+1)*50000将会失败。如果文件编号为 50000,则结果为 100000。这不是您想要的。我们需要改变原点:

$(( ((file-1)/50000+1)*50000 ))

另外,更简单的代码方案也可以:

#!/bin/bash
fsource=/opt/dms;    fdest=/opt/nes_dms;    istep=50000
cd "$fsource"
for f In *; do
    i=$(( 1+(f-1)/istep ))              # Which bucket?
    fd="$fdest/$(( istep*i ))"
    echo  \
    mv -t "$fd" "$f"
done

添加一些检查[(是目录?)和(仅数字)]:

#!/bin/bash
fsource=/opt/dms/;     fdest=/opt/nes_dms;     istep=50000
for f in "$fsource"/*; do
    [[ -d $f ]] || continue           # Is a dir?
    i=${f##*/}                        # Remove path.                                                  
    [[ $i =~ ^[0-9]+$ ]] || continue  # Only digits?                                                  
    i=$((1+(i-1)/istep))              # Which bucket?
    fd="$fdest/$(( istep*i ))"
    echo  \
                       mv -t "$fd" "$f"
done

当您对这些值感到满意并且想要执行移动时,请注释掉回显。

答案3

警告:当目录不是数字命名时,下面的脚本不会处理错误。

可能的解决方案:

#!/bin/bash
#set -x

SOURCE=/opt/dms/
DEST=/opt/nes_dms

for dir in `ls $SOURCE | sort -n`
do

  # define destination subdir
  dst_dir=$(( (($dir/50000) + 1) * 50000 ))

  # check if destination subdir exists
  if [ ! -d $DEST/$dst_dir ]
  then
    mkdir $DEST/$dst_dir
  fi 

  mv $SOURCE/$dir $DEST/$dst_dir

done

相关内容