conf t

インフラエンジニアのメモ

容量が大きいディレクトリを半分に分割するシェルスクリプト

test1ディレクトリの中に、さらにディレクトリが入れ子になっている状況。 test1ディレクトリのサイズが大きいため、test1-2ディレクトリへtest1ディレクトリのサイズが半分になるようファイルを移動したい。

# ls -l test1
合計 4
drwxr-xr-x. 28 root root 4096  7月 28 16:51 2015 s

# ls test1/s/
sa  sb  sc  sd  se  sf  sg  sh  si  sj  sk  sl  sm  sn  so  sp  sq  sr  ss  st  su  sv  sw  sx  sy  sz

汎用性は考えずにとりあえず作りました。

#!/bin/bash

path=./test1-2/s/
totalsize=`du -sm ./test1/s | cut -f 1`
halfsize=$(($totalsize / 2))



ls ./test1/s/ | while read x
do

        size=`du -sm ./test1/s/$x | cut -f 1`
        echo "size" $size
        echo "sum" $sum
        sum=$((sum + size))

        # 合計が半分を超えていたら
        if [ $sum -gt $halfsize ]; then
                echo  over

                # ディレクトリがない場合は作成する
                if [ ! -e $path ]; then
                        mkdir -p $path
                fi

                # 移動させる
                mv ./test1/s/$x ${path}

        fi

done

実行例

# du -sm ./*
1       ./test.sh
3801    ./test1
1       ./test2
1       ./test3

# ./test.sh
size 101
sum
size 101
sum 101
size 1101
sum 202
size 101
sum 1303
size 101
sum 1404
size 101
sum 1505
size 101
sum 1606
size 101
sum 1707
size 101
sum 1808
over


(省略)

size 101
sum 3321
over
size 101
sum 3422
over
size 101
sum 3523
over
size 101
sum 3624
over
size 101
sum 3725
over

# du -sm ./*
1       ./test.sh
1801    ./test1
2001    ./test1-2
1       ./test2
1       ./test3

test1が1801Mbyte,test1-2が2001Mbyteとなり、大体半分に分割できました。

最初perlawkで容量をsumしていけばワンライナーで出来ないか考えていたんですが、 perlawk実行途中でmvどうやってするのかわからなくて辞めました。

サイズを足していくperl
du -sm ./test1/s/s* | cut -f 1 | perl -ne '$sum+=$_;END{print $sum}'

サイズを足していくawk
du -sm ./test1/s/s* | awk '{sum+=$1}END{print sum}'

と思っていたんですが、頑張ったらできました。
移動先ディレクトリ作成や全体の半分のサイズはあらかじめ出しておく必要がありますが。
awkで半分をオーバしたら、ファイル名を使ってmvコマンドを作成し、それをシェルに渡します。

du -sm ./test1/s/s* | awk '{sum+=$1;if(sum>1900){print "mv " $2 " ./test1-2/s/"}}'|sh
# du -sm ./*
1       ./test.sh
1801    ./test1
2001    ./test1-2
1       ./test2
1       ./test3

参考:
ディレクトリ内のファイル名を一括で変更する(AWK) - rsnaru