我有一个perl脚本,它读取一个目录并打印出该目录的文件以及其他内容,但由于我没有读取权限,我无法这样做。
sub func {
my $some_dir = $_[0];
opendir(my $DIR, $some_dir) or die "ERROR!";
while (my $file = readdir($DIR)) {
if (-r $file) { # Read permissions
print "hurray $file!\n";
if (-d $file) { # Directory
print "entering dir...\n";
func($file);
}
} else { # No read permissions..
print "no permissions for $file\n";
}
}
return;
}
如果我使用文件夹结构运行此代码:
file
folder
-file
-file
-folder
--file
--file
我明白了:
hurray file!
hurray folder!
entering dir..
no permissions for file
no permissions for file
no permissions for file # no idea why?? should be folder
no permissions for file
no permissions for file
因此它只打印起始目录中的文件/文件夹,其他所有文件/文件夹都没有读取权限。我尝试对子目录中的所有文件执行chmod 777 file
,但我得到了相同的结果..
有什么想法吗?
感谢。
编辑 - 添加了一些东西以消除混淆。
答案 0 :(得分:3)
以下是readdir
的文档(由perldoc -f readdir
获得):
返回“opendir”打开的目录的下一个目录条目。如果在列表中使用 context,返回目录中的所有其余条目。如果没有更多 entries,在标量上下文中返回未定义的值或在列表上下文中返回空列表。
如果您计划从“readdir”中对返回值进行文件测试,则最好先添加 有问题的目录。否则,因为我们没有“chdir”那里,它会有 一直在测试错误的文件。
opendir(my $dh, $some_dir) || die "can't opendir $some_dir: $!";
@dots = grep { /^\./ && -f "$some_dir/$_" } readdir($dh);
closedir $dh;
因此:
您的if (-r $file)
无法使用,您必须说if (-r "$some_dir/$file")
。
readdir
也会返回目录'。'和'..'你可能对那些不感兴趣。
答案 1 :(得分:1)
问题是您的工作目录不会更改。例如,假设您的起始目录为/home
:
opendir(my $DIR, $some_dir) or die "ERROR!"; # working dir is /home
while (my $file = readdir($DIR)) {
if (-r $file) { # checks for /home/$file
print "hurray $file!\n"; # but path is /home/folder/$file
if (-d $file) {
print "entering dir...\n";
func($file); # enters /home/folder/$file
因此,从/home
开始,脚本无法看到文件folder/file
,或者至少不是您所指的文件。我发现在我的测试目录和我的脚本工作目录中有一些类似命名的文件会产生误报。
解决方案是适当的chdir
,或者在检查权限时添加文件名的路径。您还应该补偿.
(当前目录)和..
(父目录)。当我按原样运行你的脚本时,它变成了一个无限循环。
但当然,最好的解决方案是为工作使用适当的模块:File::Find
:
use strict;
use warnings;
use File::Find;
my $file = shift; # your file name
find(sub { if (-r) { print "Hurray $File::Find::name\n"; } }, $file);
这将以递归方式遍历文件夹并打印出与-r
权限匹配的文件名。如果您阅读File::Find
的文档,您会发现find
子例程会自动更改目录,并使用变量:
$_ # file name e.g. 'file.txt'
$File::Find::name # full relative path e.g. 'folder/file.txt'
$File::Find::dir # current folder name e.g. 'folder'