保留旧版本的 .bak 文件

保留旧版本的 .bak 文件

我刚刚学会了如何编写简单的 shell 脚本。其中之一就是简单地复制系统中对我来说至关重要的某些文件。

cp /dir/dir/file1 /samedir/samedir/file1.bak

每次登录系统时,我的脚本都会执行。但是它总是会覆盖file1.bak。我想找到一种方法来保留所有创建的文件。也许是类似的东西file1(1).bakfile1(2).bak或者类似的东西。

VMS 在某些方面非常棒,即每次有人写入一个名为的文件时file.bak,它都会通过在文件末尾添加尾随的“:”来表示版本号,从而保留所有以前的版本,即:,,,file.bak:1等等......file.bak:2file.bak:521

我们过去常常使用清除命令来删除以前的版本 purge file.bak 1-520

答案1

你可以使用一些供应链管理软件(也称为版本控制),git例如mercurialfossil

这样,您可以避免在工作目录中存储大量bak文件,同时跟踪所有以前的版本。

在我看来最简单的一个是化石-SCM 它是静态编译的单个文件,可以处理此类任务。(顺便说一下,它是由创建 SQLite 的同一位程序员创建的,因此质量很高)

你的工作流程可能是这样的:

  1. cd到需要跟踪文件的目录并使用命令初始化存储库fossil init(它将准备一个数据库文件)
  2. 告诉 Fossil 跟踪特定目录:fossil open
  3. 递归地将文件/目录添加到存储库 fossil addremove --dotfiles
  4. 将目录的当前状态保存到存储库:fossil commit或者如果您关心文件的完整性,那么:fossil commit --sha1sum

所有后续调用fossil都只是fossil commit(如果您需要添加更多新文件或从跟踪中删除一些文件,那么只需在提交之前发出fossil addremove --dotfiles

这样,对文件的所有更改都将保存在时间线中,并且可以从存储库中逐个文件进行预览、比较(差异)或提取(签出),或者完全恢复整个目录的先前状态。

您可以使用fossil extras --dotfiles它来显示新的未跟踪文件或仅发现已更改的文件fossil changes --abs-paths --sha1sum --header -v

如果您需要排除某些文件或目录,Fossil 也支持它。

您可以通过同一个文件生成的漂亮的 Web 界面查看更改的时间线,甚至可以使用内部 WiKi 对更改进行漂亮的注释。

如果您需要从存储库中删除某些内容,fossil可以提供一种称为“回避”的机制来执行此操作。

答案2

解决方案

如果您不想使用实际的版本控制系统(如@Alex&@Class Stacker 所建议的),那么以下 bash 脚本应该可以完成这项工作:

#!/bin/bash

#############
# Variables #
#############
FILE_LIST="foo.txt bar.doc"  # Space separated list of files to backup (include full path to file)
KEEP_OLD="5"  # How many previous versions to keep

#############
# Functions #
#############
function shift_backups {
        for num in $(seq $KEEP_OLD -1 1) ; do
                old_backup="$file.bak$num"
                if [[ -e $old_backup && $num == $KEEP_OLD ]] ; then
                                echo "    removing oldest file ($old_backup)"
                                rm -f $old_backup
                elif [[ -e $old_backup ]] ; then
                                new_name="$file.bak$(expr $num + 1)"
                                echo "    moving $old_backup to $new_name"
                                mv $old_backup $new_name
                fi
        done
}

################
# Backup Files #
################
for file in $FILE_LIST ; do
        count=1
        while [[ $count -le $KEEP_OLD ]] ; do
                backup_file="$file.bak$count"
                if [[ -e $backup_file ]] ; then
                        echo "$backup_file exists, shifting backups"
                        shift_backups
                        cp $file $backup_file
                        break
                else
                        cp $file $backup_file
                        break
                fi
                count=$(expr $count + 1)
        done
done

解释

为了解释这一点,我将把它分解并向您展示其中的逻辑。

变量

  • FILE_LIST变量包含要包含在备份中的所有文件的空格分隔列表(确保使用完整的文件路径)
  • KEEP_OLD变量指示何时应删除 .bak 文件。在示例中,它设置为 5,这意味着您的备份不会回溯超过 5 个版本(foo.txt.bak5 是最旧的版本)

注意:根据您要执行此操作的文件数量,可能需要调整 FILE_LIST 变量以引用文件并循环遍历其中的每一行。[我还没有测试过这个想法]

功能

该函数shift_backups执行以下操作:

  • 从最旧到最新循环查看备份文件

    for num in $(seq $KEEP_OLD -1 1) ; do
    
  • 如果备份文件存在且是最早的计数,则删除它

    if [[ -e $old_backup && $num == $KEEP_OLD ]]
    
  • 或者如果备份文件仅存在,它将被转移到backup number + 1

    elif [[ -e $old_backup ]]
    

备份循环

  • 遍历变量中的每个文件FILE_LIST

     for file in $FILE_LIST ; do
    
  • 当变量值为count1时继续循环执行备份检查

    while [[ $count -le $KEEP_OLD ]] ; do
    
  • 将目标文件名存储在变量中

    backup_file="$file.bak$count"
    
  • 如果备份文件存在,则调用 shift_backups 函数,然后复制文件(发生这种情况时会中断 while 循环)

    echo "$backup_file exists, shifting backups"
    shift_backups
    cp $file $backup_file
    break
    
  • 如果备份文件不存在,则仅复制并退出 while 循环

    else
    cp $file $backup_file
    break
    
  • 增加变量count

    count=$(expr $count + 1)
    

输出

该脚本中包含一些回显,以帮助理解它所采取的步骤。例如,下面是在最新版本的备份文件为 .bak3 的目录中运行时脚本的输出:

foo.txt.bak1 exists, shifting backups
    moving foo.txt.bak3 to foo.txt.bak4
    moving foo.txt.bak2 to foo.txt.bak3
    moving foo.txt.bak1 to foo.txt.bak2
bar.doc.bak1 exists, shifting backups
    moving bar.doc.bak3 to bar.doc.bak4
    moving bar.doc.bak2 to bar.doc.bak3
    moving bar.doc.bak1 to bar.doc.bak2

如果您需要脚本安静运行,请删除回声,它就会以相同的方式运行。

相关内容