쉘 스크립트를 사용하여 임의 범위 디렉토리를 주어진 순서대로 그룹화하는 스크립트

쉘 스크립트를 사용하여 임의 범위 디렉토리를 주어진 순서대로 그룹화하는 스크립트

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이어야 합니다.

저는 쉘 스크립팅 전문가가 아닙니다.

이것은 내 쉘 스크립트입니다.

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

관련 정보