Bash 脚本可删除早于 X 的文件夹,但跳过最新的 N...与路径中的特殊字符兼容

问题描述 投票:0回答:1

我正在 bash 中编写备份脚本,想要删除所有早于 X 天的备份,同时至少保留最新的 N 个备份。 这看起来很简单,但我还没有找到解决整个问题的方法。

就我而言,每个备份都包含一个文件夹,这些文件夹都位于同一父文件夹中。 要确定哪些备份是最新的,应使用创建或修改日期。如果这变得太复杂,我还可以按文件名的字母顺序排列(文件夹名称仅包含常量部分和日期戳 YYYYMMDD)。 我希望我的脚本适用于任何路径和文件夹名称,所以我不能假设它们不包含空格、换行符等。 它应该可以在大多数现代 Linux 系统上运行。目前我在 Ubuntu 22.04.3 LTS 上运行它。

我有一些不同的想法,但都在某种程度上有所不足。

我使用的参数

target_basefolder="/path/to/backups/parent/folder"
min_n_backups=3
backup_keepdays=28

版本 A - Oneliner

我试过这个:

find ${target_basefolder}/* -maxdepth 1 -type d -print0 | sort -rz | xargs -r0 rm -rf

但我不知道如何告诉它忽略最新的三个结果。我尝试将

tail -n +$((min_n_backups+1))
放在那里,但找不到方法告诉
tail
使用 NUL 作为分隔符而不是换行符(如 xargs 的 -0 选项)。

版本 B - 两部分

先计算文件夹数量,然后仅在有足够的较新备份时才运行删除命令。

n_backups=$(find ${target_basefolder}/* -maxdepth 1 -type d -ctime -$(backup_keepdays) -printf '.' | wc -m)
if (( $n_backups > $min_n_backups )) ; then
    find ${target_basefolder}/* -maxdepth 1 -type d -ctime +$((min_n_backups+1)) -print0 | sort -rz | xargs -r0 rm -rf
fi

这里的问题是,如果没有足够的新备份,它不会删除任何内容。例如,如果 min_n_backups 为 3 并且只有 2 个备份比 backup_keepdays 更新,则它不会删除可能 100 个旧备份中的任何一个,而不是只保留其中 1 个并删除其余备份。

版本 C - 简单循环

逐一浏览备份文件夹并检查其日期。

icount=1
for ifolder in $(find ${target_basefolder}/* -maxdepth 1 -type d -print0 | sort -rz ) ; do
    is_old=$(find "$ifolder" -maxdepth 0 -type d -ctime +$((min_n_backups+1)) -printf '.' | wc -m)
    if (( $icount > $min_n_backups && $is_old > 0 )) ; then
        rm -rf $ifolder
    fi
    ((icount++))
done

我还没有对此进行测试,特别是对于包含空格和换行符的路径。我不确定 for 循环是否可以处理 NUL 分隔的列表。如果我可以给

find
一个带有空格/换行符作为输入的文件夹名称。 但总觉得太复杂了,所以我希望我不必去那里。

版本 D - 暴力破解

我有一个想法,将最新的 N 个备份文件夹移动到另一个文件夹,然后删除比 M 旧的文件夹,然后将较新的 N 个文件夹移回来。如果文件夹很大,这可能会变慢。而且不知何故感觉不太“正确”......

我希望有人能帮我解决我的版本A或给我关于其他版本的提示。

提前致谢!

bash find xargs tail
1个回答
0
投票

您可以在管道中使用 GNU

awk
来选择目录。

find "$target_basefolder"/* -maxdepth 1 -type d -ctime -"$backup_keepdays" -print0 |
sort -zr |
awk -v RS='\0' -v ORS='\0' -v min="$min_n_backups" 'NR > min' |
xargs -0r rm -rf --
© www.soinside.com 2019 - 2024. All rights reserved.