我有一个定期更新的转储目录。
我希望删除所有超过一周的文件。
虽然我们也欢迎其他解决方案,但我们优先考虑 Bash。
答案1
诀窍在于--full-time
标志,它可以被赋予一个ls
命令,该命令返回一个文件列表,其中包含非常容易编写脚本的日期字段。我们可以轻松地按日期对其进行排序。
$ ls -l --full-time|sort -k +7
-rwxr-xr-x 1 cica cica 16536 2014-07-10 10:47:32.448349200 +0200 epl-v10.html
-rwxr-xr-x 1 cica cica 9013 2014-07-10 10:47:32.495149500 +0200 notice.html
drwxr-xr-x+ 1 cica cica 0 2014-07-07 14:12:11.502336700 +0200 readme
drwxr-xr-x+ 1 cica cica 0 2014-07-31 14:38:20.800181400 +0200 p2
drwxr-xr-x+ 1 cica cica 0 2014-07-31 15:15:06.506730000 +0200 features
drwxr-xr-x+ 1 cica cica 0 2014-07-31 15:15:06.680747400 +0200 plugins
-rw-r--r-- 1 cica cica 368634 2014-07-31 15:15:06.826762000 +0200 artifacts.xml
-rw-r--r-- 1 cica cica 329 2014-07-31 15:15:12.816360900 +0200 eclipse.ini
-rwxr-xr-x 1 cica cica 7929 2014-07-14 16:01:58.698363500 +0200 system_catalog.xml
drwxr-xr-x+ 1 cica cica 0 2014-07-31 17:41:59.205940000 +0200 configuration
-rwxr-xr-x 1 cica cica 312320 2014-06-01 20:12:16.000000000 +0200 eclipse.exe
-rwxr-xr-x 1 cica cica 17920 2014-06-01 20:12:16.000000000 +0200 eclipsec.exe
首先,我们对其进行排序经过 这 满的 日期!
诀窍是,在每天的最后一个文件之后,日期字段将在上一行之后重播。这可以通过 awk 轻松处理。
其次,我们进一步将其转化为一个简单的 awk 脚本:awk '{if ($6 == EX) print $9; EX=$6}'
最后,我们使用xargs
命令删除每个文件rm
。
完整命令是:
ls -l --full-time|sort -k +6|awk '{if ($6 == EX) print $9; EX=$6}'|xargs -P 1 -n 1 echo rm -vf
您需要定期调用此命令,最好从 cron 中调用。理想情况下,您可以将其转换为crontab -e
,每天 2:37 调用此命令:
37 2 * * * ls -l --full-time|sort -k +6|awk '{if ($6 == EX) print $9; EX=$6}'|xargs -P 1 -n 1 echo rm -vf
当然,您可以将其放入脚本中并仅从 cron 调用该脚本。
答案2
我正在寻找类似的东西,但什么也没找到,我写了自己的脚本来实现这一点。我对 bash 相当不熟悉,所以这可能可以做得更干净、更快,但这对我来说很有效。我意识到这个问题已经很老了,但仍然想回答它。
这个特定脚本的作用是:
- 永久删除早于“full_delete”的文件。
- 保留每天最新的早于“partial_delete”的文件
- 保留所有其他文件
可以进行的优化是修改硬删除以仅使用带有 delete 和 mtime 标志的 find,但我想将它们保留在一起。
#!/bin/bash
full_delete=$((60 * 60 * 24 * 30)) # 30 days
partial_delete=$((60 * 60 * 24 * 5)) # 5 days
for filename in ./data/*; do
# Check if file still exists, partial delete might've nuked it
if [ -f "$filename" ]; then
# Get epoch diff between now and when it was last modified
since_modified_epoch=$(( $(date +%s) - $(stat -L --format %Y "$filename") ))
# File is past our hard threshold, just remove
if [ $since_modified_epoch -gt $full_delete ]; then
rm "$filename"
elif [ $since_modified_epoch -gt $partial_delete ]; then
# Y-m-D file was modified
modified_date=$(date +%Y-%m-%d -r "$filename")
# Y-m-D file was modified + 1 day
modified_date_plus=$(date +%Y-%m-%d -d "$modified_date +1 days")
# Get all files where modified date is between previous 2 dates
# 'head -n -1' ignores the newest file
partial_files=$( find ./backups/ -type f -newermt "$modified_date" -not -newermt "$modified_date_plus" -printf "%T+§%p\\n" | sort | head -n -1 )
for partial_file in $partial_files; do
# Extract just filename from the line
partial_to_delete=$( echo "$partial_file" | cut -d'§' -f 2 )
rm "$partial_to_delete"
done;
fi
fi
done
您可以使用一些代码来生成测试用例。这将生成 40 天的 4 小时间隔文件。
#!/bin/bash
rm -rf ./data
mkdir -p data
for i in $(seq 1 $(( 40 * (24 / 4) )) ); do
amount=$(( i * 4 * 60 ))
touch -d "$amount minutes ago" "./data/data_$i";
done
答案3
诀窍在于--full-time
标志,它可以提供给ls
命令,为 bacvk 提供具有非常好的可编写脚本的日期字段的文件列表:
$ ls -l --full-time|sort -k +7
-rwxr-xr-x 1 cica cica 16536 2014-07-10 10:47:32.448349200 +0200 epl-v10.html
-rwxr-xr-x 1 cica cica 9013 2014-07-10 10:47:32.495149500 +0200 notice.html
drwxr-xr-x+ 1 cica cica 0 2014-07-07 14:12:11.502336700 +0200 readme
drwxr-xr-x+ 1 cica cica 0 2014-07-31 14:38:20.800181400 +0200 p2
drwxr-xr-x+ 1 cica cica 0 2014-07-31 15:15:06.506730000 +0200 features
drwxr-xr-x+ 1 cica cica 0 2014-07-31 15:15:06.680747400 +0200 plugins
-rw-r--r-- 1 cica cica 368634 2014-07-31 15:15:06.826762000 +0200 artifacts.xml
-rw-r--r-- 1 cica cica 329 2014-07-31 15:15:12.816360900 +0200 eclipse.ini
-rwxr-xr-x 1 cica cica 7929 2014-07-14 16:01:58.698363500 +0200 system_catalog.xml
drwxr-xr-x+ 1 cica cica 0 2014-07-31 17:41:59.205940000 +0200 configuration
-rwxr-xr-x 1 cica cica 312320 2014-06-01 20:12:16.000000000 +0200 eclipse.exe
-rwxr-xr-x 1 cica cica 17920 2014-06-01 20:12:16.000000000 +0200 eclipsec.exe
首先,我们对其进行排序经过 这 满的 日期!
诀窍是,在每天的最后一个文件之后,日期字段将在上一行之后重播。这可以通过 awk 轻松处理。
其次,我们进一步将其转化为一个简单的 awk 脚本:awk '{if ($6 == EX) print $9; EX=$6}'
最后,我们使用xargs
命令删除每个文件rm
。
完整命令是:
ls -l --full-time|sort -k +6|awk '{if ($6 == EX) print $9; EX=$6}'|xargs -P 1 -n 1 echo rm -vf
答案4
你也可以使用查找命令。我们将使用它来确定哪些文件已经超过一定天数,然后使用 rm 命令删除它们。
find <path of file> -typf f -mtime +0 -exec rm {} \;
它将删除昨天的文件。