找到不同路径的最新文件,但文件名相同 [英] Find up-to-date files for different paths but with identical file names

查看:290
本文介绍了找到不同路径的最新文件,但文件名相同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下文件:

  ./ 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

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


  • 我想为每个目录获取最新的文件。 li>


我构建了bash命令

  $(find。-name'file *'-type f | awk -F /'sub($ NF,x)'| sort | uniq);做
找到$ line -n​​ame'file *'-type f -printf'%T @%p \''| sort -n | tail -1 |我可以在perl中使用-f2 -d''
done

系统命令并转义 $ 。是否可以直接在Perl中执行此操作,或者您认为我的方法是否正确?
$ b 编辑

如果可能,任务应该在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脚本执行此操作,但我只想搜索文件名而不是完整的路径。所以我想搜索所有以 file 开头的文件,并且脚本应该递归地搜索。

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



所以像这样:

  use strict; 
使用警告;
使用File :: Find;

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

子想要{
return除非(-f&& / ^ file /);
my $ mod = -M $ _;
if(!defined($ times {$ File :: Find :: dir})或
$ mod< $ times {$ File :: Find :: dir} {mod}){
$次{$ File :: Find :: dir} {mod} = $ mod;
$ times {$ File :: Find :: dir} {file} = $ File :: Find :: name;






如果我在测试目录中运行这个命令,我的系统中,我得到了以下的 Data :: Dumper 结构,在这里你可以清楚地看到文件名键,存储在 / code>键,修改日期(天数与脚本运行时间相比)作为 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'
}
};


I have the following files

./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

where I marked the files I touched lastly. I want to get exactly those marked files. In other words:

  • I want to get the up-to-date file for each directory.

I constructed the bash command

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

which I am able to use in perl using the system command and escaping the $. Is it possible to do this directly in perl or do you think my approach is fine?

edit

If possible the task should be done in perl without using external modules.

edit2

Sorry, I noticed my question wasn't clear. I thought the answer of @TLP would work but I have to clearify: I want to check for the newest file in each folder, e.g. the newest file in stuff1. Say I do

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

before I run the script. It then should output:

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

The filename can be identical for different stuff but only one file per path should be output.

The script of @codnodder does this but I wish to search for only for the filename and not for the full path. So I want to search for all files beginning with file and the script should search recursively.

解决方案

Your find command can be emulated with File::Find's find command. This is a core module in Perl 5, and is almost certainly already on your system. To check the file modification time, you can use the -M file test.

So something like this:

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

If I run this command in my test directory, on my system, I get the following Data::Dumper structure, where you can clearly see the file name key, the full path stored in the file key, and the modification date (in days compared to the run time of the script) as the 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'
                 }
        };

这篇关于找到不同路径的最新文件,但文件名相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆