2017-02-11 104 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

非常感谢您的帮助 –