如何在备份期间删除旧文件但保留最近的文件?

How to delete older files but keep recent ones during backup?

我有一台远程服务器,每天将 30 多个备份文件复制到本地服务器,当且仅当新备份成功复制时,我想删除旧备份。

我尝试了不同的代码,设法删除了旧文件,但我遇到了一个问题,如果它找到一个新备份,它会删除所有旧文件。

我有类似的东西(用 20 个虚拟机想象一下):

vm001-2019-08-01.bck
vm001-2019-07-28.bck
vm002-2019-08-01.bck
vm003-2019-07-29.bck
vm004-2019-08-01.bck
vm004-2019-07-31.bck
vm004-2019-07-30.bck
vm004-2019-07-29.bck
...

我想删除所有内容,只保留最近的内容。 即:擦除:

vm001-2019-07-28.bck
vm002-2019-07-29.bck
vm004-2019-07-31.bck
vm004-2019-07-30.bck
vm004-2019-07-29.bck

只保留:

vm001-2019-08-01.bck
vm002-2019-08-01.bck
vm003-2019-07-29.bck
vm004-2019-08-01.bck

我遇到的问题是,如果我有任何机器的最近备份,像 vm-003-2019-07-29 这样的文件会被删除,因为它们较旧,即使它们来自不同的机器。

我知道这个问题在网站上有多种变体,但我不太明白这个问题。

我一直在尝试此代码的变体:

#!/bin/bash

for i in ./*.bck
do
  echo "found" "$i"
  if [[ -n $(find "$i" -type f -mmin -1440) ]]
  then
    echo "$i"
    find "$i" -type f -mmin +1440 -exec rm -f "$i" {} +
  fi
done

(回声仅用于调试目的)

此时,这段代码会找到较新和较旧的文件,但不会删除任何内容。如果我输入 find "$i" -type f -mmin +1440 -exec echo "$i" {} +,它永远不会打印任何东西,就好像 find $i 没有找到任何东西,但是当我 运行 它作为终端中的单独命令时,它会打印(减去 -exec部分)。

我已经使用 touch -d 测试了生成具有不同时间戳的文件的脚本,但没有成功。

除非您在文件名 find 之前添加 -name 测试,否则 "$i" 将被视为要搜索的目录名称。所以您的 find命令应该是:

find -name "$i" -type f -mmin -1440

它将在当前目录中搜索。或者

find /path/to/dir -name "$i" -type f -mmin -1440

它将在名为“/path/to/dir”的目录中搜索。

但是,基于 BashFAQ/099,我将执行此操作以删除除每个 VM 的最新文件之外的所有文件(未测试):

#!/bin/bash
declare -A newest  # associative array to store name of newest file for each VM
for f in *
do
    vm=${f%%-*}    # extracts vm name from filename (i.e. vmm001 from vm001-2019-08-01.bck)
    if [[ -f $f && $f -nt ${newest["$vm"]} ]]
    then
        newest["$vm"]=$f
    fi
done

for f in *
do
    vm=${f%%-*}
    if [[ -f $f && $f != ${newest["$vm"]} ]]
    then
        rm "$f"
    fi
done

这是针对当前目录中的文件设置为 运行。它假定文件的命名如问题中所示(VM 名称与文件名的其余部分用连字符分隔)。要使用关联数组,需要 Bash 4 或更高。