为什么Perl文件测试运算符“-l”没有检测到符号链接?

时间:2018-05-06 08:08:33

标签: perl file symlink

为什么Perl文件测试运算符“-l”在以下条件下无法检测到符号链接?

系统信息

john@testbed-LT:/temp2/test$ uname -a
Linux Apophis-LT 4.13.0-37-generic #42-Ubuntu SMP Wed Mar 7 14:13:23 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

john@testbed-LT:/temp2/test$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 17.10
Release:        17.10
Codename:       artful

Perl信息

john@testbed-LT:/temp2/test$ perl -v

This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux-gnu-thread-multi (with 56 registered patches, see perl -V for more detail)

测试资源

john@testbed-LT:/temp2/test$ touch regular_file
john@testbed-LT:/temp2/test$ mkdir dir
john@testbed-LT:/temp2/test$ ln -s regular_file symlink

john@testbed-LT:/temp2/test$ ls -al
total 12
drwxrwxr-x 3 john john 4096 May  6 02:29 .
drwxrwxrwx 6 john john 4096 May  6 02:29 ..
drwxrwxr-x 2 john john 4096 May  6 02:29 dir
-rw-rw-r-- 1 john john    0 May  6 02:29 regular_file
lrwxrwxrwx 1 john john   12 May  6 02:29 symlink -> regular_file

包含失败的脚本“-l”运算符

john@testbed-LT:/temp2/test$ cat ~/.scripts/test.pl
#!/usr/bin/perl

use strict;
use warnings;
use Cwd 'abs_path';

my $targetDir = "/temp2/test";
opendir(DIR, $targetDir) || die "Can't open $targetDir: $!";

while (readdir DIR) {
    my $file = "$_";

    if($file =~ m/^\.{1,2}/) {
        next;
    }

    $file = abs_path($file);

    if(-l "$file") {
        print "Link: $file\n";
    }
    elsif(-d "$file") {
        print "Dir: $file\n";
    }
    elsif(-f "$file") {
        print "File: $file\n";
    }
    else {
        print "\n\n *** Unhandled file type for file [$file]!\n\n";
        exit 1;
    }
}

closedir(DIR);

脚本输出

john@testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
File: /temp2/test/regular_file
Dir: /temp2/test/dir
File: /temp2/test/regular_file

我正试图解决的问题

请注意上面的输出中没有列出符号链接(名为“symlink”),而文件“regular_file”列出两次(我希望列出“symlink” - 实际链接和它指向的文件。)

当我在脚本中将... if(-l "$file") ...更改为... if(lstat "$file") ...时,再次列出“symlink”,而“regular_file”列出两次,但是它们是从用于捕获符号链接的块中列出的,

john@testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
Link: /temp2/test/regular_file
Link: /temp2/test/dir
Link: /temp2/test/regular_file

目标

我想要实现的输出( 以下伪造 - 实际上不是由脚本生成,而是手动生成 )是:

john@testbed-LT:/temp2/test$ perl ~/.scripts/test.pl
File: /temp2/test/regular_file
Dir: /temp2/test/dir
Link: /temp2/test/symlink

...但不一定按顺序排列(我不关心列表的顺序)。

为什么上面显示的脚本没有达到上述目标(为什么“-l”运算符不起作用)?

2 个答案:

答案 0 :(得分:7)

perldoc Cwd

  

<强>绝对路径

my $abs_path = abs_path($file);
     

使用与getcwd()相同的算法。 符号链接和相对路径组件(“。”和“..”)已解析以返回规范路径名,就像realpath(3)一样。如果错误返回undef,则会设置$!以指示错误。

(强调我的。)

如果您想查看符号链接,请不要使用abs_path

你要做的是

$file = "$targetDir/$file";

即。在前面添加$file目录的名称。

附加说明:

opendir(DIR, $targetDir) || die "Can't open $targetDir: $!";

while (readdir DIR) {
    my $file = "$_";

应该是

opendir(my $dh, $targetDir) || die "Can't open $targetDir: $!";

while (my $file = readdir $dh) {
  • 为什么在只使用普通变量(正确定义范围)时使用赤字文件句柄?
  • 这里没有理由引用"$_"
  • 为什么在下一步要将字符串复制到$_时首先分配给$file

答案 1 :(得分:4)

  

请注意,在上面的输出中,文件中没有列出符号链接(名称为&#34;符号链接&#34;),&#34; regular_file,&#34;列出两次

是的,因为您使用abs_pathsymlink转换为/temp2/test/regular_file。摆脱那条线。

顺便说一下,你错过了

$file = "$targetDir/$file";

你的程序没有它的唯一原因是因为$targetDir碰巧是当前的工作目录。