我尝试编写类似以下代码删除超过 1 个月的文件,但保留在该月 1 日创建的文件。
不同之处在于我每个月需要一个文件。
我在我的构建环境中使用该脚本,由于 scm 轮询,该脚本不会每天执行。
我认为实现此目标的唯一方法是使用 find 来获取所有“旧”文件并对其进行一些检查。
首先,我将从列表中删除所有文件,这些文件一直保留为月份文件。然后,我将从列表中删除一个文件作为月份文件,之后我将从列表中删除所有文件。
我是否错过了查找或类似功能?
答案1
概括:最完整的解决方案是最后一个,根据您到底想做什么来选择最适合您的解决方案。
实际上,如果您只想每月保留一个文件,那么您可以重命名所有文件month
。这将覆盖除每月一个文件之外的所有内容。您没有提供有关文件类型或这些文件位置的信息。我假设所有文件都在同一目录中,并且没有子目录。如果这是错误的,请更新您的问题并提供更多详细信息,我会更新我的答案。
for file in *; do
month=$(date -d `stat -c %y $file | cut -f 1 -d ' ' ` +%B);
mv $file $month;
done
上述脚本将为您留下名为 等的文件January
。February
如果您需要保留原始文件名,可以尝试以下操作:
for file in *; do
month=$(date -d `stat -c %y $file | cut -f 1 -d ' ' ` +%B);
rm *.$month;
mv $file $file.$month;
done
<FILENAME>.<MONTH>
例如,这将为您留下名为 的文件foo.January
。
上述两种解决方案都非常简单。一种更通用的解决方案也适用于子目录中的文件,并跳过不到一个月的文件:
find . -type f -mtime +29 | while IFS= read -r file; do
month=$(date -d `stat -c %y "$file" | cut -f 1 -d ' ' ` +%B);
find . -type f -name "*$month" -delete
mv "$file" "$file.$month";
done
笔记:
上述解决方案将在当前目录和所有子目录中查找至少一个月前的文件,并且每月只保留一个文件。这意味着,如果您有两个文件上次修改时间是在 1 月,其中一个是 ,另一个是
./foo
,baz/bar
则只会保留一个,要么./foo.January
或者baz/bar.January
。假设您去年没有任何可以命名为 的文件
foo.January
。如果有,这些文件将被删除。
最后,稍微复杂一点的方法可以让你保持文件名称不变,并避免上面提到的问题:
tmp=`mktemp -u XXXX`;
find . -type f -mtime +29 | while IFS= read -r file; do
date=$(date -d `stat -c %y "$file" | cut -f 1 -d ' ' ` +%B%Y);
foo=$tmp"_"$date;
find . -type f -name "*$foo" -delete
mv "$file" "$file.$foo";
done
find . -type f -name "*$tmp*" | while IFS= read -r file; do
mv "$file" "${file%.*}";
done
解释:
此脚本使用mktemp -u XXXX
(例如Xy12
)生成随机字符串,然后将其与January2008
文件的日期(例如)相结合。所有至少一个月(>29 天,抱歉,二月)的文件随后重命名为filename.Xy12_January2008
。第二个循环查找名称中包含随机字符串(Xy12
)的所有文件并删除其扩展名,因此再次filename.Xy12_January2008
变为filename
。
最终结果是每年每个月一个文件,原始文件名不变。该脚本可以处理带空格的文件名,它会在当前目录和所有子目录中查找文件。