【问题标题】:Clearing archive files with linux bash script使用 linux bash 脚本清除存档文件
【发布时间】:2013-05-27 22:17:22
【问题描述】:

这是我的问题,

我有一个文件夹,其中存储了多个具有特定格式的文件:

Name_of_file.TypeMM-DD-YYYY-HH:MM

其中 MM-DD-YYYY-HH:MM 是其创建时间。可能有多个文件同名但时间不同。

我想要的是一个可以保留每个文件的 3 个最新版本的脚本。

所以,我在那里找到了一个例子: Deleting oldest files with shell

但我不想删除一些文件,而是保留一定数量的较新文件。有没有办法获取该 find 命令,解析 Name_of_file 并保持 3 最新???

这是我已经尝试过的代码,但这并不是我所需要的。

find /the/folder -type f -name 'Name_of_file.Type*' -mtime +3 -delete

感谢您的帮助!


所以我决定添加我的最终解决方案,以防有人喜欢它。这是给出的 2 个解决方案的组合。

ls -r | grep -P "(.+)\d{4}-\d{2}-\d{2}-\d{2}:\d{2}" | awk 'NR > 3' | xargs rm

一条线,超级高效。如果日期或名称的模式发生任何变化,只需更改 grep -P 模式以匹配它。这样您就可以确定只有符合此模式的文件才会被删除。

【问题讨论】:

  • 文件格式是固定的还是可以更改的?排序YYYY-MM-DD-HH:MMMM-DD-YYYY-HH:MM 容易得多。
  • 是的,我可以改变它。这实际上很容易
  • 你打算用文件名来确定最新的3个文件吗?
  • 我认为这就是问题所在。您想改用实际的 mtime 吗?
  • 我不在乎,只要我能达到我的目标:D

标签: linux bash scripting


【解决方案1】:

您能否更加确定文件上的时间戳与文件名上的时间戳完全相同?如果他们有点偏离,你在乎吗?

ls 命令可以按时间戳顺序对文件进行排序。你可以像这样做一些事情

$ ls -t | awk 'NR > 3' | xargs rm
  • ls -t 按修改时间列出文件,最新的在前。
  • `awk 'NR > 3' 打印出文件列表前三行除外,它们是最新的三行。
  • xargs rm 将删除早于前三个的文件。

现在,这不是确切的解决方案。 xargs 可能存在问题,因为文件名可能包含奇怪的字符或空格。如果你能保证不是这样的话,应该没问题。

另外,您可能希望按名称对文件进行分组,并保留最后三个。嗯……

ls | sed 's/MM-DD-YYYY-HH:MM*$//' | sort -u | while read file
do
    ls -t $file* | awk 'NR > 3' | xargs rm
done

ls 将列出目录中的所有文件。 sed 's/\MM-DD-YYYY-HH:MM//' will remove the date time stamp from the files. Thesort -u` 将确保您只有唯一的文件名。因此

file1.txt-01-12-1950
file2.txt-02-12-1978
file2.txt-03-12-1991

将简化为:

file1.txt
file2.txt

这些是通过循环放置的,ls $file* 将列出以文件名和后缀开头的所有文件,但会将其通过管道传递给awk,这将去除最新的三个,并将其传递给xargs rm 将删除除最新的三个之外的所有内容。

【讨论】:

  • 不错!它工作得很好。我有几个错误。每个未删除的文件一个。 (rm:缺少操作数 尝试使用 `rm --help' 获取更多信息。)我会处理的,不用担心。非常感谢!
【解决方案2】:

假设我们使用文件名中的日期来确定存档文件的日期,并且可以将日期格式更改为YYYY-MM-DD-HH:MM(如上面的 cmets 中所建立),这里有一个快速而肮脏的 shell 脚本来保存当前工作目录中每个文件的最新3 版本:

#!/bin/bash
KEEP=3  # number of versions to keep

while read FNAME; do
    NODATE=${FNAME:0:-16}  # get filename without the date (remove last 16 chars)
    if [ "$NODATE" != "$LASTSEEN" ]; then  # new file found
        FOUND=1; LASTSEEN="$NODATE"
    else  # same file, different date
        let FOUND="FOUND + 1"
        if [ $FOUND -gt $KEEP ]; then
            echo "- Deleting older file: $FNAME"
            rm "$FNAME"
        fi
    fi
done < <(\ls -r | grep -P "(.+)\d{4}-\d{2}-\d{2}-\d{2}:\d{2}")

示例运行:

[me@home]$ ls
another_file.txt2011-02-11-08:05  
another_file.txt2012-12-09-23:13  
delete_old.sh
not_an_archive.jpg 
some_file.exe2011-12-12-12:11             
some_file.exe2012-01-11-23:11 
some_file.exe2012-12-10-00:11  
some_file.exe2013-03-01-23:11  
some_file.exe2013-03-01-23:12

[me@home]$ ./delete_old.sh 
- Deleting older file: some_file.exe2012-01-11-23:11
- Deleting older file: some_file.exe2011-12-12-12:11

[me@home]$ ls
another_file.txt2011-02-11-08:05
another_file.txt2012-12-09-23:13
delete_old.sh
not_an_archive.jpg
some_file.exe2012-12-10-00:11
some_file.exe2013-03-01-23:11
some_file.exe2013-03-01-23:12

本质上,但是将文件名更改为表单中的日期为YYYY-MM-DD-HH:MM,正常的字符串排序(如ls 所做的)会自动将相似的文件分组在一起,按日期时间排序。

最后一行的ls -r 仅列出当前工作中的所有文件,直接以相反的顺序打印结果,因此较新的存档文件首先出现。

我们通过grep 传递输出以仅提取格式正确的文件。

然后循环该命令组合的输出(参见while 循环),我们可以在相同文件名出现 3 次后开始删除(减去日期部分)。

【讨论】:

  • 当我尝试运行脚本第 15 行时出现此错误:`done
  • 错误信息是什么?你似乎是一个&lt; 短。应该是done &lt; &lt;(....)
【解决方案3】:

此管道将为您提供当前目录中的 3 个最新文件(按修改时间)

stat -c $'%Y\t%n' file* | sort -n | tail -3 | cut -f 2-

获取所有最新的 3 个:

stat -c $'%Y\t%n' file* | sort -rn | tail -n +4 | cut -f 2-

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2012-09-09
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    相关资源
    最近更新 更多