备份系统的shell脚本[关闭]

Posted

技术标签:

【中文标题】备份系统的shell脚本[关闭]【英文标题】:shell script to backup system [closed] 【发布时间】:2017-06-30 01:23:55 【问题描述】:

我正在使用以下格式将备份文件保存在文件中 backup#01.tar.gz ,backup#02.tar.gz 等。 但现在我需要循环备份目录以找到最大的数字并将下一个文件增量命名为它例如:backup#03.tar.gz 有什么帮助吗?

【问题讨论】:

确实可以做你想做的事,但是如何使用包含可排序格式的时间戳的文件(例如 YYYY-MM-DD_HHhMM)?这将回避问题并在文件名中提供其他信息。 【参考方案1】:

这是一个不需要子shell 或外部程序的解决方案,不解析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"

【讨论】:

当前的 printf 表达式填充到 4 (backup#0001.tar.gz) 的长度,而 OP 要求填充到 2。 我其实是把它从2改成了4,觉得这样会更好(超过命名格式之前99个备份好像不是很多)。 %02 而不是 %04 会将其恢复为 2 位数。匹配不会以任何特定长度阻塞,并且数字比较将忽略前导零,因此这只是一个表面问题,并且命名将继续正常超出printf 格式字符串中的位数。 谢谢它的工作【参考方案2】:

有几种方法可以做到这一点,当然,我将简单地假设您的脚本将以某种方式从这些备份所在的目录运行,否则只需调整。

#!/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

我写它是为了不言自明,所以我确信有更有效或更紧凑的方法可以做到这一点,但这应该有助于您在更宏大的计划中适应/插入它。

所以,总结一下操作:

倒序列出文件夹中匹配“backup*tar.gz”的所有文件 为文件名指定一个此类文件的名称。第一个将是我们最新的现有备份。 结合使用expr数组操作提取数字并转换为整数,表示最后一个备份数字 使用 expr 将此类整数值加一 使用 printf 格式化新的备份文件名,包括填充 重要打破循环,因为我们已经知道这个循环中的第一个文件是最新的备份文件,所以我们可以退出。

当然,您可以更改获取文件名的方式。

数组操作可以方便地应用于 bash 中的字符串,请查看http://tldp.org/LDP/abs/html/arrays.html

编辑:在@Fred 的宝贵输入之后,虽然坚持使用ls 为我对文件进行排序,但以下不会产生那么多子shell,它使用 bash 自己的算术和来自@ 的非常有用的-v 选项987654326@:

#!/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

【讨论】:

不推荐解析ls 输出(mywiki.wooledge.org/ParsingLs)。如果只需要第一行输出(使用read 和进程替换<()),则不需要循环。您还启动了许多子shell:虽然没有错,但没有必要,因为您可以使用 shell 算法、printf 的 -v 选项、shell 扩展/匹配。 @Fred 很棒的补充。考虑到 OP 有一个固定的命名方案,采用非常受控的 ls 解析应该不会像最一般的情况那么糟糕。 Shell 算术绝对是我将添加到我的答案中的东西,以及新的我建议-v 选项到printf。谢谢! 非常感谢您的帮助

以上是关于备份系统的shell脚本[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统shell脚本之定期清理备份文件

Linux系统shell脚本之mysql的日志备份

shell脚本--系统文件备份之脚本分析

Linux shell : 史上最简单的系统备份脚本

linux/unix系统间文备份脚本

shell脚本怎么实现日志备份到本地Linux系统