【问题标题】:need to to sort directories based on the pattern yyyymmdd需要根据模式 yyyymmdd 对目录进行排序
【发布时间】:2014-02-15 06:03:00
【问题描述】:

我有一个路径,我将在其中创建许多格式为“test_1.2.3_yyyymmdd”的目录

例如test_1.2.3_20140214

一个常见的事情是,我将始终将日期(以 yyyymmdd 格式)作为目录名称的一部分。理想情况下的文件 以不同的日期以相同的方式创建。

我的要求是根据目录名称中的日期字段对文件进行排序,我可以使用以下命令来实现

ls | sort -t_ -k3,3

但是,有时创建目录时,日期不是目录名称的最后一个字段。即使在这种情况下,我也想要 根据日期字符串对文件进行排序。有人可以告诉我如何实现这一目标。

如果我能够实现这种排序,那么我必须删除最旧的文件(基于 yyyymmdd 模式)。要求是路径应始终包含最新的 10 基于上述排序的目录,如果超过 10 个,则我必须删除最旧的目录。

我不能指望 find 命令,因为这不是基于 -mtime

我想为此依靠 UNIX 工具/Perl 编程。

【问题讨论】:

  • 每个文件名是否最多包含一个由八个连续数字组成的子字符串?
  • 嗨 Rob,文件名中不会有任何其他部分有八个连续数字。八位数字(日期 yyyymmdd)只会出现一次
  • "... 我必须删除最旧的文件(基于 yyyymmdd 模式)。" 如果两个或多个文件具有相同的 yyyymmdd 会怎样?
  • 不会这样,但是是的,如果是,我也必须删除它们。
  • 如果您不确定目录名称是否包含正确的时间戳,为什么不对文件运行“stat”,找到正确的时间戳并采取适当的行动。为什么需要依赖不正确且可能陈旧的元数据。

标签: perl unix


【解决方案1】:

这里有一个可供考虑的选项:

use strict;
use warnings;
use List::Util qw/min/;

my %files;

while ( my $file = <DATA> ) {
    chomp $file;
    my ($date) = $file =~ /([^_]+)$/;
    push @{ $files{$date} }, $file;
}

local $, = "\n";
print @{ $files{ min keys %files } };

__DATA__
test_1.2.3_20140214
test_A.B.C_20140214
test_X.Y.Z_20140212
test_1.2.3_20140210
test_4.5.6_20140210

输出:

test_1.2.3_20140210
test_4.5.6_20140210

$VAR1 = {
          '20140210' => [
                          'test_1.2.3_20140210',
                          'test_4.5.6_20140210'
                        ],
          '20140212' => [
                          'test_X.Y.Z_20140212'
                        ],
          '20140214' => [
                          'test_1.2.3_20140214',
                          'test_A.B.C_20140214'
                        ]
        };

首选使用split,但您提到日期字符串可能不是文件名的最后一部分。因此,您需要某种方式(split,正则表达式,...)来获取它。

在上述脚本中,这些日期用作数组哈希 (HoA) 中的键,而值是对文件路径列表的引用。来自List::Utilmin 用于查找最小键值,因为那将是最旧的日期。

使用 HoA,以防有多个文件具有相同的 yyyymmdd。

而不是printing 结果,将数组传递给unlink 以删除文件,即unlink @{ $files{ min keys %files } };

散列的Data::Dump 显示其结构。

希望这会有所帮助!

【讨论】:

  • 感谢您的回复,将尝试利用您的建议。我觉得最好的方法是,检查路径中的目录数是否大于 10,如果是,则根据可用的 yyyymmdd 对文件进行排序,然后执行 $count=current_dir_count - 10 然后将其删除 ls | sort -t_ k3,3 | head -$count | xargs rm -rf 但我唯一的问题是,如果日期不是文件名的第三个字段怎么办:(
  • @chidori 不客气!您说,“...如果日期不是文件名的第三个字段怎么办...”这绝对是您需要解决的问题。
  • @chidori - 如果日期字符串总是是文件名中唯一的八位数字,您可以执行以下操作来捕获它:my ($date) = $file =~ /(\d{8})/;
  • 感谢 Kenonsis 以及所有分享他们观点的人。我正在增强 Kenonsis 代码,以满足我的要求 :) 当目录计数超过 10 时,我需要旧文件列表,所以我根据之后创建的文件数对键进行排序并删除顶部文件目录计数超过 10
猜你喜欢
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多