查找不同路径的最新文件,但文件名相同

时间:2013-12-12 10:30:01

标签: perl bash find

我有以下文件

./path/to/stuff1/file1    (x)
./path/to/stuff1/file2
./path/to/stuff1/file3

./path/to/stuff2/file1
./path/to/stuff2/file2    (x)
./path/to/stuff2/file3

./path/to/stuff3/file1    (x)
./path/to/stuff3/file2
./path/to/stuff3/file3

我标记了我最后触及的文件。我想得到那些标记的文件。换句话说:

  • 我想获取每个目录的最新文件

我构造了bash命令

for line in $( find . -name 'file*' -type f | awk -F/ 'sub($NF,x)' | sort | uniq ); do
        find $line -name 'file*' -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2 -d' '
done

我可以使用system命令在perl中使用并转义$。是否可以直接在perl中执行此操作,或者您认为我的方法是否正常?

修改

如果可能,任务应该在perl中完成而不使用外部模块。

EDIT2

抱歉,我注意到我的问题不明确。我认为@TLP的答案可行但我必须澄清:我想检查每个文件夹中的最新文件,例如 stuff1 中的最新文件。说我做

touch ./path/to/stuff1/file1
touch ./path/to/stuff2/file2
touch ./path/to/stuff3/file1

在我运行脚本之前。然后输出:

./path/to/stuff1/file1
./path/to/stuff2/file2
./path/to/stuff3/file1

对于不同的东西,文件名可以相同,但每个路径只能输出一个文件。

@codnodder的脚本执行此操作,但我希望仅搜索文件名而不是完整路径。所以我想搜索以文件开头的所有文件,脚本应该递归搜索。

2 个答案:

答案 0 :(得分:1)

您的find命令可以使用File::Find find命令进行模拟。这是Perl 5中的核心模块,几乎肯定已经在您的系统上。要检查文件修改时间,可以使用-M文件测试。

这样的事情:

use strict;
use warnings;
use File::Find;

my %times;
find(\&wanted, '.');
for my $dir (keys %times) {
    print $times{$dir}{file}, "\n";
}

sub wanted {
    return unless (-f && /^file/);
    my $mod = -M $_;
    if (!defined($times{$File::Find::dir}) or
        $mod < $times{$File::Find::dir}{mod}) {
        $times{$File::Find::dir}{mod} = $mod;
        $times{$File::Find::dir}{file} = $File::Find::name;
    }
}

如果我在我的测试目录中运行此命令,在我的系统上,我会得到以下Data::Dumper结构,您可以在其中清楚地看到文件名密钥,file密钥中存储的完整路径,以及修改日期(与脚本运行时间相比的天数)为mod

$VAR1 = {
          './phone' => {
                         'file' => './phone/file.txt',
                         'mod' => '3.47222222222222e-005'
                       },
          './foo' => {
                       'file' => './foo/fileb.txt',
                       'mod' => '0.185'
                     },
          '.' => {
                   'file' => './file.conf',
                   'mod' => '0.154490740740741'
                 }
        };

答案 1 :(得分:1)

我能想到3种一般方法。

  1. 使用opendir(),readdir()和stat()。
  2. 使用File :: Find。
  3. 使用glob()。
  4. 最合适的选择取决于您拥有的具体内容 使用,我们无法从您的帖子中看到。

    另外,我假设当你说“没有外部模块”时,你不是 排除使用Perl安装的模块(即在Core中)。

    以下是使用glob()的示例:

    use File::Basename qw/fileparse/;
    
    for my $file (newest_file()) {
        print "$file\n";
    }
    
    sub newest_file {
        my %files;
        for my $file (glob('./path/stuff*/file*')) {
            my ($name, $path, $suffix) = fileparse($file);
            my $mtime = (stat($file))[9];
            if (!exists $files{$path} || $mtime > $files{$path}[0]) {
                $files{$path} = [$mtime, $name];
            }
        }
        return map { $files{$_}[1] } keys %files;
    }