手作りのファイルリポジトリをハッシュされたリポジトリに移行して、Webアプリケーション(主にPHPアプリ)からアクセスおよび管理するために、過去に使用したBashスクリプトがいくつかあります。これらのリポジトリでは、ファイル名がハッシュされ(同じコンテンツ/名前のファイルとの衝突を回避するため)、パフォーマンス上の理由から、ディレクトリあたりのファイル数を低く抑えるために、ファイルが均等に(決定論的またはランダムに)分散されます。以下は、完全に機能する1つの例です。
#!/bin/bash
MAXFILESPERDIR=500
TARGETROOTDIR="./newrepository"
RANDOMDISTRIBUTION=1
if [ -d "$1" ]; then
LOGFILE=$(basename $0).$(date +"_%Y%m%d_%H%M").${$}.log
SQLFILE=$(basename $0).$(date +"_%Y%m%d_%H%M").${$}.sql
SOURCEDIR="$1"
TOTALSOURCEFILES=$(find "$1" -type f | wc -l)
let "TOTALTARGETDIRS=$TOTALSOURCEFILES / $MAXFILESPERDIR"
PADLENTARGETDIRS=${#TOTALTARGETDIRS}
PADLENTARGETFILE=${#TOTALSOURCEFILES}
echo "We will create $TOTALTARGETDIRS directories to hold $MAXFILESPERDIR files per directory."
if [ "$RANDOMDISTRIBUTION" == "1" ] ; then
echo "We will rename and distribute each file randomly."
else
echo "We will rename and distribute each file uniformly."
fi
echo "Do you want to continue?"
select choice in yes no ; do
if [ "$choice" == "yes" ] ; then
COUNTER=1
find "$1" -type f | while read SOURCEFILE ; do {
CHECKSUMFILE=$(sha1sum "$SOURCEFILE" | cut -d " " -f 1)
CHECKSUMNAME=$(echo "$SOURCEFILE" | sha1sum | cut -d " " -f 1)
DETERMINISTICNONCE=$(printf "%0${PADLENTARGETFILE}d\n" $COUNTER)
if [ "$RANDOMDISTRIBUTION" == "1" ] ; then
PROBABILISTICNONCE=$(let "XX=$RANDOM % $TOTALTARGETDIRS + 1" ; printf "%0${PADLENTARGETDIRS}d\n" $XX;)
else
PROBABILISTICNONCE=$(let "XX=$COUNTER % $TOTALTARGETDIRS + 1" ; printf "%0${PADLENTARGETDIRS}d\n" $XX;)
fi
FILEDATE=$(stat -c %z "$SOURCEFILE" | cut -d "." -f 1)
FILESIZE=$(stat -c %s "$SOURCEFILE")
echo "Source file $SOURCEFILE" >> $LOGFILE
echo "Target file $TARGETROOTDIR/$PROBABILISTICNONCE/$PROBABILISTICNONCE$CHECKSUMFILE$DETERMINISTICNONCE" >> $LOGFILE
echo "INSERT INTO files (Filename, Location, Checksum, CDate, Size) VALUES ('$PROBABILISTICNONCE$CHECKSUMFILE$DETERMINISTICNONCE', '$PROBABILISTICNONCE', '$CHECKSUMFILE', '$FILEDATE', $FILESIZE);" >> $SQLFILE
mkdir -p $TARGETROOTDIR/$PROBABILISTICNONCE
cp -v "$SOURCEFILE" $TARGETROOTDIR/$PROBABILISTICNONCE/$PROBABILISTICNONCE$CHECKSUMFILE$DETERMINISTICNONCE
let "COUNTER+=1"
} ; done
echo "Done."
echo
break
fi
if [ "$choice" == "no" ] ; then
echo
echo "Operation cancelled"
echo
break
fi
done
else
echo
echo "Missing source directory"
echo
fi
新しいリポジトリのルートから実行するだけです。最初の変数を変更して構成できます。MAXFILESPERDIRは、ディレクトリごとに保存するファイルの数を定義します。TARGETROOTDIRは、最初のレベルのディレクトリを作成するための最初のレベルのディレクトリの名前です(2つのレベルのみを使用し、最初のレベルは実際には1つです。 root)、およびRANDOMDISTRIBUTIONは、ファイルをランダムに配布するか(特に小さな実行の場合は不均一に見える場合があります)、決定論的に(カウントするだけで)配布するかを定義します。
それがどのように機能するか(参考までに、これがあなたが探しているものではない場合に備えて、多分あなたはいくつかのアイデアを得ることができます):
- ソースファイルを数えます。
- 作成するターゲットディレクトリの数を計算します。
- 確認を求めます。
- ファイルごとに:
- ファイルコンテンツのSHA1ハッシュを計算します。
- 決定論的ナンスを作成します。
- 確率的ナンスを作成します(RANDOMDISTRIBUTIONが1の場合、それ以外の場合はカウンターのみ)。
- サイズと変更日を取得します。
- ランダム値の値をハッシュおよびカウンターと組み合わせて、新しいファイル名を取得します(パスはランダム値になります)。
- ソースとターゲットのフルパスをログに記録します。
- SQL挿入クエリを作成してログに記録します。
- ターゲットディレクトリを作成します(存在しない場合)。
- ファイルをコピーします。(必要に応じて移動できますが、私は安全にプレイしています)。
- 終了
RANDOMDISTRIBUTIONを1に設定し、スクリプトを数回実行すると、実行するたびに各ファイルが異なるターゲットファイル名/パスを取得するため、ソースファイルの複製が取得されます。RANDOMDISTRIBUTIONが別の値に設定されている場合、スクリプトを実行するたびに、ファイルの名前が同じように変更されます(同じファイルセットの場合、ファイルを追加または削除すると、異なる名前/パスが取得されます)。
ランダム値+ハッシュ+カウンターを使用する目的は、ファイルをランダムに分散しながら(カウンターのおかげで衝突しない)、重複を確実に処理できるようにすることです(十分な長さの実行では、ファイルが均等に分散されます)。
また、生成されたファイル名の接頭辞はディレクトリの名前でもあるため、ファイル名とディレクトリ名の長さがわかっている場合は、ディレクトリ名を計算できます(データベースに保存しない場合に備えて)。テーブル)。
最後に、これは1回限りの移行スクリプトであり、同じファイルセットに対して定期的に実行されるように作成されたものではありません。