2013-12-12 24 views
0

我有以下文件找到了最新的文件不同的路径,但具有相同的文件名

./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 '%[email protected] %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脚本执行此操作,但我希望仅搜索文件名而不是完整路径。所以我想搜索以文件开头的所有文件,并且脚本应该递归搜索。

回答

1

您的find命令可以用File::Findfind命令来模拟。这是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' 
       } 
     }; 
+0

很抱歉的混乱,但我只注意到你的脚本不输出期望的文件。我编辑了这个问题...... – EverythingRightPlace

+0

这只是改变目录名称的关键,而不是我现在所做的。 – TLP

+0

太棒了,thx很多! – EverythingRightPlace

1

有3种我能想到的一般方法。

  1. 使用opendir(),readdir()和stat()。
  2. 使用File :: Find。
  3. 使用glob()。

最合适的选择取决于您的 要使用的具体细节,我们无法从您的发布中看到。

此外,我假设当你说“没有外部模块”,你不是 排除与Perl(即在核心)安装的模块。

下面是使用水珠()的例子:

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; 
} 
+0

对不起,忘了提及我正在使用Perl 5.10.1。是的,使用核心模块没有问题。 – EverythingRightPlace

+0

您的脚本也可以使用。我将一行改为'$ files {$ path} = [$ mtime,“$ path $ name”];'这让我获得了所需的文件路径输出。希望接受这两个答案,thx家伙。 – EverythingRightPlace

相关问题