我有一个每日备份,名称如下:
yyyymmddhhmm.zip // pattern
201503200100.zip // backup from 20. 3. 2015 1:00
我正在尝试创建一个脚本来删除所有超过 3 天的备份。该脚本还应该能够删除文件夹中与该模式不匹配的所有其他文件(但脚本中会有一个开关来禁用此功能)。
为了确定文件期限,我不想使用备份时间戳,因为其他程序也会操作文件并且它可能会被篡改。
在...的帮助下:在 UNIX 中删除超过 5 天的文件(文件名中的日期,而不是时间戳) 我有:
#!/bin/bash
DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups/
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)
ls -1 ${BACKUPS_PATH}????????????.zip |
while read A DATE B FILE
do
[[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
done
if [ $DELETE_OTHERS == "yes" ]; then
rm ${BACKUPS_PATH}*.* // but I don't know how to not-delete the files matching pattern
fi
但它一直在说:
rm: missing operand
问题出在哪里以及如何完成脚本?
答案1
您的代码中的第一个问题是您是解析ls
。这意味着如果文件或目录名中有空格,它很容易被破坏。您应该使用 shell 通配符或find
代替。
更大的问题是你没有正确读取数据。你的代码:
ls -1 | while read A DATE B FILE
永远不会填充$FILE
。的输出ls -1
只是文件名列表,因此,除非这些文件名包含空格,否则只会read
填充您指定的 4 个变量中的第一个。
这是脚本的工作版本:
#!/usr/bin/env bash
DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)
## Find all files in $BACKUPS_PATH. The -type f means only files
## and the -maxdepth 1 ensures that any files in subdirectories are
## not included. Combined with -print0 (separate file names with \0),
## IFS= (don't break on whitespace), "-d ''" (records end on '\0') , it can
## deal with all file names.
find ${BACKUPS_PATH} -maxdepth 1 -type f -print0 | while IFS= read -d '' -r file
do
## Does this file name match the pattern (13 digits, then .zip)?
if [[ "$(basename "$file")" =~ ^[0-9]{12}.zip$ ]]
then
## Delete the file if it's older than the $THR
[ "$(basename "$file" .zip)" -le "$THRESHOLD" ] && rm -v -- "$file"
else
## If the file does not match the pattern, delete if
## DELETE_OTHERS is set to "yes"
[ $DELETE_OTHERS == "yes" ] && rm -v -- "$file"
fi
done
答案2
在 FreeBSD 中使用: 示例:在 /usr/home/foobar 中查找 foobar 拥有的所有早于 5760 分钟(4 天)的文件并将其删除。
find /usr/home/foobar -user foobar -type f -mmin +5760 -delete
答案3
不要忘记和 sed
之间的线,这条线很重要。ls -1
while read
对于第一个问题,我建议:( awk 替代品我无法找到 sed 等效项)
ls -1 ${BACKUPS_PATH}????????????.zip |\
awk -F. '{printf "%s %s\n",$1,$0 ;}' |\
while read DATE FILE
do
[[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
done
提供的 shell 算术至少是 37 位来进行测试$DATE -le $THRESHOLD
。