为什么Perl文件测试运算符“是”-l";不检测符号链接?

为什么Perl文件测试运算符“是”-l";不检测符号链接?,perl,file,symlink,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 a

为什么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
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)
Perl信息

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
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
我试图解决的问题

请注意,在上面的输出中,符号链接(名为“符号链接”)未列出,而文件“常规文件”列出了两次(我希望列出“符号链接”——实际链接和它指向的文件

当我改变
。。。如果(-l“$file”)…
。。。如果脚本中有(lstat“$file”)…
,则“符号链接”不会列出,而“常规文件”会列出两次,但它们是从用于捕获符号链接的块中列出的,即:

目标

我试图实现的输出(,下面是伪造的——实际上不是由脚本生成的,而是手工生成的)是:

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

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

abs\u路径

my $abs_path = abs_path($file);
使用与getcwd()相同的算法符号链接和相对路径组件(“.”和“.”
解析为返回规范路径名,就像realpath(3)一样。On error返回
unde
,带有
$设置以指示错误

(我的重点。)

如果要查看符号链接,请不要使用
abs\u path

你想做的是

$file = "$targetDir/$file";
i、 e.在前面加上您从中读取的目录名
$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) {
  • 当您可以只使用普通变量(范围正确)时,为什么要使用裸字文件句柄
  • 没有理由在这里引用
    “$\u”
  • 在下一步中要将字符串复制到
    $文件
    时,为什么要首先分配给
    $\uuu
请注意,在上述输出中,符号链接(名为“符号链接”)未列出,而文件“常规_文件”列出了两次

是的,因为您使用了
abs\u路径
symlink
转换为
/temp2/test/regular\u文件
。摆脱那条线


顺便说一下,你失踪了

$file = "$targetDir/$file";

程序在没有它的情况下运行的唯一原因是因为
$targetDir
恰好是当前的工作目录。

Perl不是缩写。
$file=abs\u path($file)应该是
$file=“$targetDir/$file”。我现在没有时间去寻找更多的问题。为什么你一直使用
“$file”
而不是
$file
?@ikegami:因为,一旦我完成了这个简单的测试,我计划将它扩展到递归目录,其中一些路径可能包含空格,而且,因为我对Perl比较陌生,我认为引用$file更安全,以防它包含空格(或其他字符),可能会引起混淆。@JohnDoe空格没有“不安全”的地方。
$file
只是一个变量;它可以包含它想要的任何字符串。Perl不是shell;它不会通过重复的文本替换来计算命令。”程序在没有它的情况下工作的唯一原因是$targetDir恰好是当前的工作目录。“是的,在我昨晚发布我的问题后,我确实注意到了这一点。谢谢很好的解释。我以前使用变量作为文件句柄。我改成光着身子抓稻草。关于引文,我一直在思考BASH扩展,并期望路径包含空格和非字母数字字符(需要思维转移)。为了可读性,我将$分配给$文件(1),因为脚本将大大扩展,并且在最终脚本中会大量访问当前文件;(2)因为我最终还将对列出的原始符号链接和指向的文件(单独存储)执行操作.@JohnDoe将
$分配给
$文件
不会增加可读性,如果您可以首先剪切
$并读入
$文件