Perl uses the find function to get into trouble

Preface

I wrote a script that can check multiple simulation log files at the same time and generate html tables. Sort files from newest to oldest by modification time. Then I have been unable to use the stath function to obtain ctime.

Conclusion: The find function will change the current directory where the program is executed , find(\&process_files, $dir);and the function is run in the $dir directory .

text

The directory structure of the test environment is as follows:

.
├── check_logs.pl
└── logs
    ├── 1.txt
    ├── 2.txt
    └── 3.txt

1 directory, 4 files

1. Use the built-in function stat

Perl provides a built-in function stat() to obtain file-related information, and the function returns an array.

Official documentation introduces stat - Perldoc browser

my($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($file_name);

Introducing some of the more important meanings:

  • $dev and $ino
    • The number of the device where the file is located and the inode number of the file.
  • $mode
    • A collection of permission bits for a file, along with other bits of information. The lower 9 bits are the Linux permission bits.
  • $nlink
    • The number of hard links to the file or directory.
  • $uid and $gid
    • Numeric representation of the user ID and group ID of the file owner
  • $size
    • File size in bytes
  • $atime, $mtime and $ctime
    • Three timestamps, a 32-bit integer representing the number of seconds since 1970.
    • Access time (atime): The access time records the last time the file was read. Whenever a file is read, its access timestamp is updated. This can be useful for certain applications, such as log auditing or tracking how often a file is accessed.
    • Modification time (mtime): The modification time records the last time the file content was modified. When a file's content (data) is modified, its modification timestamp is updated. This is useful for determining when a file was last modified.
    • Change time (ctime): The change time records the last time the file metadata was changed. Metadata is non-data information related to a file, such as the file's permissions, owner, or file type. When these metadata properties change, their change timestamps are updated.

Let’s first look at the code that uses the built-in function to get the modification time.

#! /bin/perl -w
use strict;
use warnings;
use File::Find;
use File::Basename;

my $time = (stat("./logs/1.txt"))[10];
print "$time\n";

The running results are as follows:

[fengbh@VM-16-14-centos perl_stat]$ ./check_logs.pl 
1703579691

2. Use File::stat

File::stat will override the built-in system function, which provides functions similar to the built-in function stat in a class manner.

Official Documentation File::stat - by-name interface to Perl's built-in stat() functions - Perldoc Browser

The code to obtain the modification time using a class is as follows:

#! /bin/perl -w
use strict;
use warnings;
use File::Find;
use File::stat;

my $time = stat("./logs/1.txt")->mtime;
print "$time\n";

The running results are as follows:

[fengbh@VM-16-14-centos perl_stat]$ ./check_logs.pl 
1703579691

3. Use in File::Find

This is implemented using built-in functions.

#! /bin/perl -w
use strict;
use warnings;
use File::Find;

my $dir = "./logs";
find(\&process_files, $dir);

sub process_files{
    
    
    return if !-f $_;
    
    #debug
    print "\$_ = $_\n";
    print "\$File::Find::name = $File::Find::name\n\n";

    #get mtime
    my $mtime = (stat($File::Find::name))[10];
    die "Can't stat file;$!\n" if !defined($mtime);

    # debug
    print "mtime = $mtime\n";
}

operation result:

[fengbh@VM-16-14-centos perl_stat]$ ./check_logs.pl 
$_ = 3.txt
$File::Find::name = ./logs/3.txt

Can't stat file;No such file or directory

When running, an error is reported and the file cannot be found. But the file pathname passed to the stat function is correct.

This is because the find function will change the current directory where the program is executed , or it can be understood that the process_files function is run in the $dir directory .

This is the reason for the error. $File::Find::name is the path relative to the initial execution directory, and $_ is the path relative to $dir.

Modify the code to:

#! /bin/perl -w
use strict;
use warnings;
use File::Find;

my $dir = "./logs";
find(\&process_files, $dir);

sub process_files{
    
    
    return if !-f $_;
    
    #debug
    print "\$_ = $_\n";
    print "\$File::Find::name = $File::Find::name\n\n";

    #get mtime
    my $mtime = (stat($_))[10];
    die "Can't stat file;$!\n" if !defined($mtime);

    # debug
    print "mtime = $mtime\n";
}

The execution results are as follows:

[fengbh@VM-16-14-centos perl_stat]$ ./check_logs.pl 
$_ = 3.txt
$File::Find::name = ./logs/3.txt

mtime = 1703577429
$_ = 1.txt
$File::Find::name = ./logs/1.txt

mtime = 1703579691
$_ = 2.txt
$File::Find::name = ./logs/2.txt

mtime = 1703577426

The execution result is correct

references

  1. Official documentation introduces stat - Perldoc browser
  2. Official Documentation File::stat - by-name interface to Perl's built-in stat() functions - Perldoc Browser
  3. "Introduction to Perl Language"

Guess you like

Origin blog.csdn.net/weixin_44681954/article/details/135226741