2017-02-11 167 views
-7

我將備份文件保存在一個文件中,使用以下格式備份#01.tar.gz,備份#02.tar.gz等。 但現在我需要循環備份目錄找到最大的數字並命名下一個文件增量到它:備份#03.tar.gz 任何幫助嗎?shell腳本備份系統

+0

這肯定是可以做到你想要什麼,但如何使用包含在可排序格式的時間戳的文件(如YYYY-MM-DD_HHhMM)?這將回避問題並提供文件名中的其他信息。 – Fred

回答

3

這是一種不需要子shell或外部程序的解決方案,母鹿s不解析ls輸出(這是不推薦的),並且應該使用包含空格的文件名(甚至是換行符)。您可以自定義您的前綴和擴展名。

#!/bin/bash 
dir="/path/to/files" 
prefix="backup#" 
ext=".tar.gz" 
max=1 
for file in "$dir/$prefix"* 
do 
    [[ $file =~ /$prefix([0-9]+)$ext$ ]] || continue 
    n="${BASH_REMATCH[1]}" 
    [[ $max -gt $n ]] || max=$((n+1)) 
done 
printf -v newfilename "$prefix%04d$ext" "$max" 
+0

當OP詢問填充爲2時,當前'printf'表達式的長度爲4'(備份號#0001.tar.gz)''。 – sal

+0

我實際上已將其從2更改爲4,認爲它會更好(在超過命名格式之前的99次備份看起來不是很多)。 '%02'而不是'%04'會將它返回到2位數。匹配不會阻塞任何特定的長度,數字比較將忽略前導零,所以這只是一個表面問題,並且命名將繼續超過「printf」格式字符串中的位數。 – Fred

+0

謝謝你的工作 –

0

有幾種方法可以做到這一點,當然,我將簡單地假設您的腳本將以某種方式從這些備份所在的目錄運行,否則只需進行調整。

#!/bin/bash 
for filename in `ls backup*tar.gz -r -1`; do 
    echo "Last backup file found is $filename" 
    last=`expr ${filename[@]:7:2}` 
    next=`expr $last + 1` 
    newname=`printf "backup#%02d.tar.gz" $next` 
    echo "Next backup file should be $newname" 
    break # important!!! 
done 

我寫這樣的,這是自我解釋,所以我肯定有更有效或緊湊的方式做同樣的,但這應該幫助你適應/在你窮的東西方案插入。

所以,總結一下操作:按相反的順序

  • 列表中的文件夾匹配的「備份* tar.gz的」
  • 所有文件分配的一個這樣的文件名。第一個將是我們最新的現有備份。
  • 使用EXPR陣列操作的組合來提取的數目和轉換爲整數,其表示上次備份數
  • 增加這樣的整數值由一個與EXPR
  • 使用的printf格式化新的備份文件名,包括填充
  • 重要打破循環,因爲我們已經知道這個循環中的第一個文件是最新的備份文件,所以我們可以退出。

當然,您可以更改文件名的獲取方式。

有關數組操作可以很方便地應用到在bash字符串參考,檢查http://tldp.org/LDP/abs/html/arrays.html

編輯:後@弗雷德的寶貴意見,同時使用ls排序的文件對我來說,下面沒有按粘「T產卵多達子shell,它使用bash的自己的算法,並從printf相當有用-v選項:

#!/bin/bash 
for filename in `ls backup*tar.gz -r -1`; do 
    echo "Last backup file found is $filename" 
    last="${filename[@]:7:2}" 
    printf -v newname "backup#%02d.tar.gz" $((last+1)) 
    echo "Next backup file should be $newname" 
    break # important!!! 
done 
+0

不推薦解析'ls'輸出(http://mywiki.wooledge.org/ParsingLs)。如果你只需要輸出的第一行(使用'read'和一個進程替換'<()'),則不需要循環。你也可以啓動許多子shell:雖然沒有錯,但沒有必要,因爲你可以使用shell運算,printf的shell命令'-v',shell擴展/匹配。 – Fred

+0

@Fred很好的補充。考慮到OP有一個固定的命名方案,訴諸於一個非常受控的'ls'解析不應該像最一般的情況一樣糟糕。殼算術絕對是我將添加到我的答案,以及新的我建議'-v'選項'printf'。謝謝! – sal

+0

非常感謝您的幫助 –