I’m trying to write a script that prints out the file structure starting at the folder the script is located in. The script works fine without the recursive call but with that call it prints the contents of the first folder and crashes with the following message: closedir() attempted on invalid dirhandle DIR at printFiles.pl line 24. The folders are printed and the execution reaches the last line but why isn’t the recursive call done? And how should I solve this instead?
#!/usr/bin/perl -w
printDir(".");
sub printDir{
opendir(DIR, $_[0]);
local(@files);
local(@dirs);
(@files) = readdir(DIR);
foreach $file (@files) {
if (-f $file) {
print $file . "\n";
}
if (-d $file && $file ne "." && $file ne "..") {
push(@dirs, $file);
}
}
foreach $dir (@dirs) {
print "\n";
print $dir . "\n";
printDir($dir);
}
closedir(DIR);
}
You should always
use strict;anduse warnings;at the start of your Perl program, especially before you ask for help with it. That way Perl will show up a lot of straightforward errors that you may not notice otherwise.The invalid filehandle error is likely because
DIRis a global directory handle and has been closed already by a previous execution of the subroutine. It is best to always used lexical handles for both files and directories, and to test the return code to make sure the open succeeded, like thisOne advantage of lexical file handles is that they are closed implicitly when they go out of scope, so there is no need for your
closedircall at the end of the subroutine.localisn’t meant to be used like that. It doesn’t suffice as a declaration, and you are creating a temporary copy of a global variable that everything can access. Best to usemyinstead, like thisAlso, the file names you are using from
readdirhave no path, and so your file tests will fail unless you eitherchdirto the directory being processed or append the directory path string to the file name before testing it.