保留备份脚本中的n个最新目录

时间:2017-06-07 01:28:58

标签: linux bash unix backup

我在/home/backup/中有一个存储年度备份的目录。在备份文件夹中,我们有以下目录:

/home/backup/2012
/home/backup/2013
/home/backup/2014
/home/backup/2015
/home/backup/2016
/home/backup/2017

每年我都要清理数据,只保留最后三年的备份。

在上述情况下,我必须删除:

/home/backup/2012
/home/backup/2013
/home/backup/2014

找到要删除的目录的最佳方法是什么?我有这个,但它不起作用:

find /home/ecentrix/recording/ -maxdepth 1 -mindepth 1 -type d -ctime +1095 -exec rm -rf {} \;

你们有另一个想法吗?

6 个答案:

答案 0 :(得分:8)

由于您的目录有明确定义的整数名称,我只是使用bash来计算适当的目标:

mkdir -p backup/201{2..7} # just for testing

cd backup
rm -fr $(seq 2012 $(( $(date +"%Y") - 3)))

seq生成一个从2012年到当前年份减3的数字列表,然后传递给rm进行爆破。

答案 1 :(得分:4)

解决方案

# Check if extended globbing is on
shopt extglob

# If extended globbing is off, run this line
shopt -s extglob

# Remove all files except 2015, 2016, and 2017
rm -r -i /home/backup/!(2015|2016|2017)

# Turn off extended globbing (optional)
shop -u extglob

解释

shopt -s extglob可让您匹配除!(...)内的文件以外的任何文件。因此,该行意味着删除/home/backup201520162017以外的所有文件。

-i中的rm -r -i ...标记允许您以交互方式确认删除每个文件。如果您希望自动删除文件,请删除-i

动态日期

此解决方案适用于自动化(例如cron作业)

# Number of latest years to keep
LATEST_YEARS=3

# Get the current year
current_year=$(date '+%Y')

# Get the first/earliest year to keep
first_year=$(( current_year - $(($LATEST_YEARS - 1)) ))

# Turn on extended globbing
shopt -s extglob

# Store years to keep in an array
keep_years=( $(seq $first_year $current_year) )

# Specify files to keep
rm -r /home/backup/!(${keep_years[0]}|${keep_years[1]}|${keep_years[2]})
  

注意:备份目录中的所有文件将被删除,除了最近3年

答案 2 :(得分:4)

更通用的解决方案

我认为最好按降序遍历目录,然后删除第三个目录之后的目录。这样,当脚本一次又一次地运行时,没有丢失目录的危险:

#!/bin/bash
backups_to_keep=3
count=0
cd /home/backup
while read -d '' -r dir; do
  [[ -d "$dir" ]]                || continue  # skip if not directory
  ((++count <= backups_to_keep)) && continue  # skip if we are within retaining territory
  echo "Removing old backup directory '$dir'" # it is good to log what was cleaned up
  echo rm -rf -- "$dir"
done < <(find . -maxdepth 1 -name '[2-9][0-9][0-9][0-9]' -type d -print0 | sort -nrz)

测试后删除echo之前的rm -rf。对于您的示例,它提供此输出:

rm -rf -- ./2014
rm -rf -- ./2013
rm -rf -- ./2012
  • cd /home/backuprm -rf限制在该目录以提高安全性
  • find . -maxdepth 1 -name '[2-9][0-9][0-9][0-9]' -type d提供与glob
  • 匹配的顶级目录
  • sort -nrz确保首先显示较新的目录,-z处理find ... -print0的空终止输出
  • 这个解决方案并没有对这些年进行硬编码 - 它只是假设要删除的目录以数字排序的方式命名
  • 它对备份目录中存在的任何其他文件或目录具有弹性
  • 如果一次又一次地运行脚本,则没有副作用
  • 这可以很容易地扩展,以支持备份目录的不同命名约定 - 只需更改glob表达式

答案 3 :(得分:3)

考虑一下:

find /home/backup/2* -maxdepth 1 | sort -r | awk "NR>3" | xargs rm -rf

如何运作

  1. 仅在 / home / backup /

  2. 下生成以“2”开头的文件名列表
  3. 按字母顺序对列表进行排序,顺序相反。

  4. 使用AWK过滤列表中的行数。 NR 指定反向排序行的数量。您可以将该3更改为要保留的行数。因此,如果您只想要最近两年,请将 3 更改为 2 。如果您希望保留最新的10,请将其设为“NR&gt; 10”

  5. 将结果列表附加到命令“rm -rf”。

  6. 以专用用户身份运行,以确保安全

    这里的危险是我建议 rm -rf 。这是有风险的。如果出现问题,您可以删除要保留的内容。我只通过专用用户调用这些命令来减轻这种风险,该专用用户只有删除备份文件的权限(而不是超出)。

    优异

    这种方法的优点是,当你把它扔进一个cron作业并且时间推进时,它将继续只保留最新的几个目录。所以,我认为这是解决问题的一般方法。

    示范

    为了测试这个,我创建了一个包含所有相同目录的测试目录。我改变它只是为了看看最后会执行什么,所以我试过了:

    find test01/2* -maxdepth 1 | sort -r | awk "NR>4" | xargs echo rm -rf
    

    我使用了NR&gt; 4而不是NR&gt; 3(正如您所希望的那样),因为NR&gt; 4表示我们正在选择要从列表中删除的行数,因此不会删除。

    这是我得到的: Demonstration

    上面的倒数第二个命令将最后阶段改为 echo 它会做什么,但实际上是这样做的。

    我在脚本中有一个转储的原始副本,因为我在我的一些服务器上使用它,你可以在这里查看:https://github.com/docdawning/teenybackup

    成功必需

    此方法取决于 find 命令产生的字母顺序。在我的例子中,我使用ISO-8601 type dates,它完全适合于在按字母顺序排列时固有的日期排序。您的YYYY类型日期完全符合条件。

    额外安全

    我建议您更改备份以存储为tar存档。然后,您可以将 rm -rf 更改为简单的 rm 。这样更安全,但不是万无一失。无论如何,你真的应该把它作为一个专门的非特权用户运行(在我看来你应该为任何调用删除的脚本做)。

    请注意,如果您使用

    启动它
    find /home/backup
    

    然后对xargs的调用将包含/ home / backup本身,这将是一场灾难,因为它也会被删除。所以你必须在那条路径内搜索。用以下方法调用它会起作用:

    find /home/backup/* 
    

    上面给出的2 *只是一种限制搜索操作的方法。

    保修

    无;这是互联网。小心。大量测试以说服自己。此外,也可能获得一些离线备份。

    最后 - 我之前发布了这个作为答案,但是在 / home / backup 而不是 / home / backup / * / home / backup / 2 * 。这导致 / home / backup 也被发送删除,这将是一场灾难。这是一个非常小的区别,我试图在上面清楚。我删除了之前的答案,并将其替换为此答案。

答案 4 :(得分:0)

这是一种方式。

更新了答案。

[dev]$ find backup/*  | grep -vE "$(date '+%Y')|$(date +%Y --date='1 year ago')|$(date +%Y --date='2 year ago')" | xargs  rm -rfv

removed directory: ‘backup/2012’
removed directory: ‘backup/2013’
removed directory: ‘backup/2014’

答案 5 :(得分:-3)

如果要删除目录,则应键入以下命令

sudo rm -r [folder name]
#in your case it will be 
sudo rm -r /home/backup/2012
sudo rm -r /home/backup/2013
sudo rm -r /home/backup/2014