2012-06-06 20 views
1

我有一個高度結構化的分層目錄,其中包含需要移動到平面結構並同時重命名的多個文件。原始路徑和名稱必須與新路徑和名稱一起記錄,並最終加載到數據庫中。最後,每個重命名的文件都必須得到一個唯一的,不可猜測的(IE:加密或散列)文件名。當重命名的文件移動到新的目錄結構中時,我也想限制每個目錄中的文件數量,因此每個目錄都將創建一個連續的數字作爲其名稱,然後文件將被加載到最大在滾動到具有下一個連續編號名稱的新目錄之前,已達到文件數(例如:255)。批量重命名/移動/散列文件

有沒有這樣的工具/軟件?我做了一些初步的研究,並沒有想出了以下標準:

  • 批量重命名&拷貝到替代(扁平化)的結構
  • 散列/加密文件名,並確保其唯一性
  • 順序名稱的文件夾和限制文件數
  • 日誌中的每個文件的原始名稱和路徑,以及新的(加密)的名稱和路徑

回答

1

我有我已經在過去使用到m幾個Bash腳本將手工製作的文件存儲庫遷移到散列存儲庫,以便通過Web應用程序(主要是PHP應用程序)進行訪問和管理。在這些存儲庫中,文件名被散列(以避免與具有相同內容/名稱的文件發生衝突)並且文件均勻分佈(以確定性方式或隨機分佈)以保持每個文件的文件數量低於性能原因。以下是一個完整的示例:

#!/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是創建第一級目錄的第一級目錄的名稱(它只使用兩個級別,第一個是真正的單一目錄根),RANDOMDISTRIBUTION定義文件是否隨機分佈(它可能看起來不均勻,特別是對於小批量運行)或確定性(只是計數)。

它是如何工作(僅供參考,以防萬一這是不是你在找什麼,但也許你可以得到一些想法):

  1. 計數的源文件。
  2. 計算將創建多少個目標目錄。
  3. 請求確認。
  4. 對於每個文件:
    • 計算文件內容的SHA1哈希值。
    • 創建確定性隨機數。
    • 創建概率隨機數(如果RANDOMDISTRIBUTION爲1,否則只是一個計數器)。
    • 獲取大小和修改日期。
    • 將隨機值的值與散列和計數器組合以獲得新文件名(路徑將是隨機值)。
    • 記錄源和目標完整路徑。
    • 創建並記錄SQL插入查詢。
    • 創建目標目錄(如果它不存在)。
    • 複製文件。 (你可以移動它,如果你想,但我玩的很安全)。
  5. 完成

如果設置RANDOMDISTRIBUTION爲1並運行該腳本幾次,你會得到你的源文件的副本,因爲每個文件將每次運行得到不同的目標文件名/路徑它。如果將RANDOMDISTRIBUTION設置爲其他內容,則每次運行腳本時,文件都將以相同的方式重命名(對於相同的文件集,如果添加或刪除文件,它們將得到不同的名稱/路徑)。

使用隨機值+散列+計數器的目的是確保我們可以處理重複(不會因計數器而發生碰撞),同時仍然隨機分發文件(對於足夠長的運行,這將分配文件均勻)。

此外,生成文件名的前綴也是該目錄的名稱,以便如果您有文件名和目錄名稱長度,則可以計算目錄名稱(以防萬一您不存儲在你的數據庫表中)。

最後,這是一次性遷移腳本,它並沒有真正寫入通過同一組文件定期執行。