递归 Perl 详细信息需要帮助
我认为这是一个简单的问题,但我已经坚持了一段时间了!我需要用一双新的眼光来看待这个问题。
问题是我在 perl 中有这段代码:
#!c:/Perl/bin/perl
use CGI qw/param/;
use URI::Escape;
print "Content-type: text/html\n\n";
my $directory = param ('directory');
$directory = uri_unescape ($directory);
my @contents;
readDir($directory);
foreach (@contents) {
print "$_\n";
}
#------------------------------------------------------------------------
sub readDir(){
my $dir = shift;
opendir(DIR, $dir) or die $!;
while (my $file = readdir(DIR)) {
next if ($file =~ m/^\./);
if(-d $dir.$file)
{
#print $dir.$file. " ----- DIR\n";
readDir($dir.$file);
}
push @contents, ($dir . $file);
}
closedir(DIR);
}
我试图让它递归。我需要拥有所有目录和子目录的所有文件以及完整路径,以便我将来可以打开这些文件。
但我的输出仅返回当前目录中的文件以及它找到的第一个目录中的文件。如果我的目录中有 3 个文件夹,它只显示第一个。
前任。 cmd 调用:
"perl readDir.pl directory=C:/PerlTest/"
谢谢
i think this is a simple problem, but i'm stuck with it for some time now! I need a fresh pair of eyes on this.
The thing is i have this code in perl:
#!c:/Perl/bin/perl
use CGI qw/param/;
use URI::Escape;
print "Content-type: text/html\n\n";
my $directory = param ('directory');
$directory = uri_unescape ($directory);
my @contents;
readDir($directory);
foreach (@contents) {
print "$_\n";
}
#------------------------------------------------------------------------
sub readDir(){
my $dir = shift;
opendir(DIR, $dir) or die $!;
while (my $file = readdir(DIR)) {
next if ($file =~ m/^\./);
if(-d $dir.$file)
{
#print $dir.$file. " ----- DIR\n";
readDir($dir.$file);
}
push @contents, ($dir . $file);
}
closedir(DIR);
}
I've tried to make it recursive. I need to have all the files of all of the directories and subdirectories, with the full path, so that i can open the files in the future.
But my output only returns the files in the current directory and the files in the first directory that it finds. If i have 3 folders inside the directory it only shows the first one.
Ex. of cmd call:
"perl readDir.pl directory=C:/PerlTest/"
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
避免重新发明轮子,使用 CPAN。
确保您不会让人们将
$dir
设置为会让他们查看您不希望他们查看的位置的内容。Avoid wheel reinvention, use CPAN.
Make sure that you don't let people set
$dir
to something that will let them look somewhere you don't want them to look.您的问题是目录句柄 DIR 的范围。
DIR
具有全局作用域,因此对readDir
的每个递归调用都使用相同的DIR
;因此,当您closdir(DIR)
并返回到调用者时,调用者会对关闭的目录句柄执行readdir
操作,然后一切都会停止。解决方案是使用本地目录句柄:另请注意,如果 (a) 它不在
$directory
末尾或 (b) 在每个递归调用中,您将丢失目录分隔符。 AFAIK,斜杠将在 Windows 上内部转换为反斜杠,但无论如何你可能想使用 CPAN 的路径修改模块(我只关心 Unix 系统,所以我没有任何建议)。我还建议您将对
@contents
的引用传递给readDir
而不是将其保留为全局变量,这样可以减少错误和混乱。并且不要在sub
定义上使用括号,除非您确切知道它们的用途和用途。对$directory
进行一些健全性检查和清理也是一个好主意。Your problem is the scope of the directory handle
DIR
.DIR
has global scope so each recursive call toreadDir
is using the sameDIR
; so, when youclosdir(DIR)
and return to the caller, the caller does areaddir
on a closed directory handle and everything stops. The solution is to use a local directory handle:Also notice that you would be missing a directory separator if (a) it wasn't at the end of
$directory
or (b) on every recursive call. AFAIK, slashes will be internally converted to backslashes on Windows but you might want to use a path mangling module from CPAN anyway (I only care about Unix systems so I don't have any recommendations).I'd also recommend that you pass a reference to
@contents
toreadDir
rather than leaving it as a global variable, fewer errors and less confusion that way. And don't use parentheses onsub
definitions unless you know exactly what they do and what they're for. Some sanity checking and scrubbing on$directory
would be a good idea as well.有许多模块可用于递归列出目录中的文件。
我最喜欢的是 File::Find::Rule
它将文件列表发送到数组中(您的程序正在执行此操作)。
还有很多其他选项,例如仅列出具有特定名称的文件。或者您可以将其设置为迭代器,如 中所述如何使用 File::Find
如何我在 Perl 中使用 File::Find?
如果您想坚持使用 Perl Core 附带的模块,请查看 File::Find。
There are many modules that are available for recursively listing files in a directory.
My favourite is File::Find::Rule
Which sends a list of files into an array ( which your program was doing).
There a loads of other options, like only listing files with particular names. Or you can set it up as an iterator, which is described in How can I use File::Find
How can I use File::Find in Perl?
If you want to stick to modules that come with Perl Core, have a look at File::Find.