LoginSignup
0
0

More than 1 year has passed since last update.

ディレクトリ内にある大量のファイル達を管理しやすいように複数ディレクトリに分割する

Last updated at Posted at 2021-08-19

沢山は扱いづらい

0.はじめに

大容量ストレージにデータを保存する時、特に画像データなんかは1つのディレクトリ(フォルダ)に大量のデータが割と無作為に入れることが多いと思われます。自分の場合は古いHDDからデータをサルベージした際、1つのディレクトリに14万もの画像データが入ることになりました。そうすると、普通のファイラーを使った際にデータが多すぎてファイラーの処理が重くなったりして使いづらくなります。
綺麗に分類分け出来ればもちろんいいのですが、流石に量が量なのでとりあえず適当に分割することを考えます。

1.分け方

とりあえず、ディレクトリ内の大量ファイル達を$n$等分することを考えます。
ここでは単純に考えて1つのディレクトリを2つに分けて半分に、更にその2つのディレクトリを2つずつに分けて更に半分に、…
というのを繰り返してねずみ講のように$2^k$個にディレクトリを分けて$2^k$分割する方法を取ります。(2,4,8,16,32,...)
14万個データがあるディレクトリを32分割すると大体4400個になり、まあ頑張れば扱いきれる数になります。(分割のバランスを考えるとこれくらいが妥当でしょうか。)

2.アルゴリズム

さて分け方は考えましたが、コンピュータにやらせるためにもう少しロジックを考える必要があります。アルゴリズムを考えるというヤツです。
結論から書くと以下のようになります。

対象ディレクトリに対する処理
1. 対象のディレクトリ内のファイル数を数えて、その半分を算出する
2. 対象のディレクトリ内のファイル一覧を出力し、その後半部分を出力する
3. ディレクトリをもう一つ作成し、対象ディレクトリ内の後半部分ファイルをそこに移動する

3.スクリプト

最終的なbash scriptは以下の通りです。
所々にあるecho文は役割としてはprintデバッグの側面が強いので無くても問題なし。

ディレクトリ内の大量ファイルを分割整理する
#!/bin/bash
# ディレクトリ内の大量ファイルを2**n分割してディレクトリに分ける

if [ $# -ne 1 ]; then
    echo "引数の数が違う"
    exit 1
fi

# 対象のディレクトリとそこのパスを切り分ける
splite_directory=$(basename $1)
readonly splite_directory
base_directory=$(dirname $1)
readonly base_directory

echo $splite_directory
echo $base_directory

target_dir_list=($splite_directory)
count=1
while [ $count -lt 32 ]
do
    new_target_dir_list=()
    for t_dir in ${target_dir_list[@]};
    do
        echo $t_dir
        # ディレクトリ内のファイル数を数えて、その半分値を算出する
        num_file=$(find ${base_directory}/${t_dir}/. -type f|wc -l)
        half_num=$(($num_file>>1))
        echo $num_file
        echo $half_num

        # 対象のディレクトリ内のファイル一覧を出力し、その後半部分を作成する
        ls -1 ${base_directory}/${t_dir}/. > file_list.txt
        tail -q -n $half_num file_list.txt > half_list.txt
        half_files=(`cat half_list.txt|xargs`)
        rm file_list.txt
        rm half_list.txt

        # ディレクトリを2つに分割し、収納ファイル数を半分に分ける
        rename_dir=${t_dir}0
        new_dir=${t_dir}1
        new_target_dir_list+=(${rename_dir} ${new_dir})

        # 収納ファイルの後ろ半分を新しいディレクトリに移す
        mkdir ${base_directory}/${new_dir}
        for hf in ${half_files[@]};
        do
            mv ${base_directory}/${t_dir}/${hf} ${base_directory}/${new_dir}/${hf}
        done

        # 移し元のディレクトリを改名する
        mv ${base_directory}/${t_dir} ${base_directory}/${rename_dir}
    done

    target_dir_list=${new_target_dir_list[@]}
    count=$(($count<<1))
done
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0