为什么 Perl 文件测试运算符“-l”不检测符号链接?
Why does Perl file test operator "-l" not detect symlinks?
为什么 Perl 文件测试运算符“-l”在以下条件下无法检测到 symlinks?
系统信息
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(名为 "symlink")未列出,而文件 "regular_file," 列出了两次(我希望列出 "symlink" -- 实际 link 而 而不是 它指向的文件)。
当我在脚本中将 ... if(-l "$file") ...
更改为 ... if(lstat "$file") ...
时,再次未列出 "symlink" 而 "regular_file" 列出了两次,但它们是从块意味着捕捉 symlinks,i.e.:
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”运算符不起作用)?
abs_path
my $abs_path = abs_path($file);
Uses the same algorithm as getcwd(). Symbolic links and relative-path components ("." and "..") are resolved to return the canonical pathname, just like realpath(3). On error returns undef
, with $!
set to indicate the error.
(强调我的。)
如果您想查看符号链接,请不要使用 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
时先分配给 $_
?
Note in the above output that the symlink (named "symlink") is not listed while the file, "regular_file," is listed twice
是的,因为你用abs_path
把symlink
变成了/temp2/test/regular_file
。摆脱那条线。
对了,你不见了
$file = "$targetDir/$file";
你的程序在没有它的情况下运行的唯一原因是因为 $targetDir
恰好是当前工作目录。
为什么 Perl 文件测试运算符“-l”在以下条件下无法检测到 symlinks?
系统信息
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(名为 "symlink")未列出,而文件 "regular_file," 列出了两次(我希望列出 "symlink" -- 实际 link 而 而不是 它指向的文件)。
当我在脚本中将 ... if(-l "$file") ...
更改为 ... if(lstat "$file") ...
时,再次未列出 "symlink" 而 "regular_file" 列出了两次,但它们是从块意味着捕捉 symlinks,i.e.:
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”运算符不起作用)?
abs_path
my $abs_path = abs_path($file);
Uses the same algorithm as getcwd(). Symbolic links and relative-path components ("." and "..") are resolved to return the canonical pathname, just like realpath(3). On error returns
undef
, with$!
set to indicate the error.
(强调我的。)
如果您想查看符号链接,请不要使用 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
时先分配给$_
?
Note in the above output that the symlink (named "symlink") is not listed while the file, "regular_file," is listed twice
是的,因为你用abs_path
把symlink
变成了/temp2/test/regular_file
。摆脱那条线。
对了,你不见了
$file = "$targetDir/$file";
你的程序在没有它的情况下运行的唯一原因是因为 $targetDir
恰好是当前工作目录。