1

フラット構造に移動し、同時に名前を変更する必要がある複数のファイルを含む高度に構造化された階層ディレクトリがあります。元のパスと名前は、新しいパスと名前とともにログに記録され、最終的にデータベースにロードされる必要があります。最後に、名前が変更された各ファイルは、一意の推測できない(つまり、暗号化またはハッシュ化された)ファイル名を取得する必要があります。名前が変更されたファイルが新しいディレクトリ構造に移動されるとき、各ディレクトリ内のファイルの数も制限したいので、各ディレクトリはその名前の連番で作成され、ファイルは最大になるまでそこにロードされます名前に次の連続番号が付いた新しいディレクトリにロールインする前に、ファイルの数(例:255)に達しました。

これを行うツール/ソフトウェアはありますか?私はいくつかの初期調査を行いましたが、次の基準は何も思いつきませんでした。

  • バッチの名前変更と代替(フラット)構造へのコピー
  • ファイル名をハッシュ/暗号化し、一意性を確保します
  • フォルダに順番に名前を付け、ファイル数を制限する
  • 各ファイルの元の名前とパス、および新しい(暗号化された)名前とパスをログに記録します
4

1 に答える 1

1

手作りのファイルリポジトリをハッシュされたリポジトリに移行して、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は、ファイルをランダムに配布するか(特に小さな実行の場合は不均一に見える場合があります)、決定論的に(カウントするだけで)配布するかを定義します。

それがどのように機能するか(参考までに、これがあなたが探しているものではない場合に備えて、多分あなたはいくつかのアイデアを得ることができます):

  1. ソースファイルを数えます。
  2. 作成するターゲットディレクトリの数を計算します。
  3. 確認を求めます。
  4. ファイルごとに:
    • ファイルコンテンツのSHA1ハッシュを計算します。
    • 決定論的ナンスを作成します。
    • 確率的ナンスを作成します(RANDOMDISTRIBUTIONが1の場合、それ以外の場合はカウンターのみ)。
    • サイズと変更日を取得します。
    • ランダム値の値をハッシュおよびカウンターと組み合わせて、新しいファイル名を取得します(パスはランダム値になります)。
    • ソースとターゲットのフルパスをログに記録します。
    • SQL挿入クエリを作成してログに記録します。
    • ターゲットディレクトリを作成します(存在しない場合)。
    • ファイルをコピーします。(必要に応じて移動できますが、私は安全にプレイしています)。
  5. 終了

RANDOMDISTRIBUTIONを1に設定し、スクリプトを数回実行すると、実行するたびに各ファイルが異なるターゲットファイル名/パスを取得するため、ソースファイルの複製が取得されます。RANDOMDISTRIBUTIONが別の値に設定されている場合、スクリプトを実行するたびに、ファイルの名前が同じように変更されます(同じファイルセットの場合、ファイルを追加または削除すると、異なる名前/パスが取得されます)。

ランダム値+ハッシュ+カウンターを使用する目的は、ファイルをランダムに分散しながら(カウンターのおかげで衝突しない)、重複を確実に処理できるようにすることです(十分な長さの実行では、ファイルが均等に分散されます)。

また、生成されたファイル名の接頭辞はディレクトリの名前でもあるため、ファイル名とディレクトリ名の長さがわかっている場合は、ディレクトリ名を計算できます(データベースに保存しない場合に備えて)。テーブル)。

最後に、これは1回限りの移行スクリプトであり、同じファイルセットに対して定期的に実行されるように作成されたものではありません。

于 2012-06-17T12:39:33.363 に答える