シェルスクリプトを使用して任意の範囲ディレクトリを指定された順序でグループ化するスクリプト

シェルスクリプトを使用して任意の範囲ディレクトリを指定された順序でグループ化するスクリプト

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

関連情報