注意:虽然 jeff-schaller 给出了答案,但这取决于zsh
;所以我想得到一个基于的答案Bash
。
我喜欢创建一个 Bash 脚本来有条件地从备份目录中删除旧文件。
两个不同的文件备份有两个条件:
1、保留 的最新副本Edge_Profile_*.tgz
,并删除 的其余部分Edge_Profile_*.tgz
仅限超过 5 天的情况。
2、保留 的最新副本Firefox_Profile_*.tgz
,并删除 的其余部分Firefox_Profile_*.tgz
,无论他们多大年纪。
以下是我修改此 AskUbuntu 答案的方法:https://askubuntu.com/a/933098/928088
脚本:
#!/bin/bash
LOG_FILE="/home/admn/Cleanup.log"
TEMP_LOG="/tmp/Temp_Cleanup.log"
mv $LOG_FILE $TEMP_LOG
{
cd /home/admn/Downloads/Test;
echo "Cleanup log:" `date`
find /home/admn/Downloads/Test/Edge_Profile_*.tgz -type f \( -mtime +5 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
case "$flag" in
'Y') echo rm "$file"
;;
*) echo "skipping $file (too new)"
;;
esac;
done
echo
find /home/admn/Downloads/Test/Firefox_Profile_*.tgz -type f \( -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
case "$flag" in
'Y') echo rm "$file"
;;
*) echo "skipping $file (too new)"
;;
esac
done
} &>> $LOG_FILE
cat $TEMP_LOG >>$LOG_FILE
exit;
在日志文件中输出echo
:
/usr/local/scripts/cleanup.sh
rm /home/admn/Downloads/Test/Edge_Profile_Jul_06_2021_00-35.tgz
rm /home/admn/Downloads/Test/Edge_Profile_Jul_07_2021_00-35.tgz
....
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new)
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new)
....
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_01_2021_00-35.tgz
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_02_2021_00-35.tgz
....
在实际运行脚本时在日志文件中输出,无需echo
:
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new): No such file or directory
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new): No such file or directory
....
目录中的文件总数:20 个文件
1、Edge_Profile_*.tgz:7月6日至7月17日:12个文件
2、Firefox_Profile_*.tgz:7月1日至7月8日:8个文件
问题:
(1)我思考该脚本可以运行,但我不太确定,因为我修改了大部分内容但不知道发生了什么。
(2)输出到日志文件:
我希望日志文件中的输出与所获得的输出完全相同echo
,除了文件名(不带完整路径),例如:
rm Edge_Profile_Jul_11_2021_00-35.tgz
skipping Edge_Profile_Jul_12_2021_00-35.tgz (too new)
操作系统:Ubuntu MATE 21.04
多谢。
答案1
在可以直接访问文件的 shell 中,根据文件的修改时间进行操作要容易得多。zsh 就是这样一个 shell。只需sudo apt install zsh
安装它即可。由于您的文件似乎位于一个目录中,因此此答案是非递归的。首先演示更简单的情况:
保留 Firefox_Profile_*.tgz 的最新副本并删除其余文件(无论它们有多旧):
echo would rm -v -- Firefox_Profile_*.tgz(.om[2,-1])
echo would
如果看起来正确,则删除该部分。这使用glob(通配符)限定符括号内做三件事:- 仅选择普通文件(不是目录或套接字等)
.
- 按修改时间对文件进行排序,从最新到最旧,
om
- 从第二个元素开始到末尾选择结果列表的一部分 - 跳过第一个(最新)文件,使用
[2,-1]
如果没有匹配的文件,zsh 将停止并显示“zsh:未找到匹配项”,并且不会执行
rm
。- 仅选择普通文件(不是目录或套接字等)
为了保留 Edge_Profile_*.tgz 的最新副本并删除超过 5 天的其余副本,首先我们获取最新的副本:
newest=(Edge_Profile_*.tgz(.om[1]))
...然后我们得到超过五天的数据:
older=(Edge_Profile_*.tgz(.m+5))
这里的新部分是
+5
修饰符m
。它选择超过 5 天的文件。之后,我们确保最新的文件不在要删除的列表中:remove=("${(@)older:|newest}")
这里的新部分是数组减法符号
:|
;它记录在zsh 手册的参数扩展部分。它选择“older”中不属于“newest”的元素。最后,我们删除该文件列表:echo would rm -v -- "${remove[@]}"