Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

here's the subroutine I have made to generate a recursive list (with path) of every file in a directory. My problem is that it hangs up on files with square brackets in the filename, and I don't know how to fix this.

sub recursive_filelist { my $dir = $_[0]; $dir .= '/' if($dir !~ /\/$/); $dir .= '*'; my @list = glob($dir); my @files; foreach my $variable (@list) { my $full = $path . $variable; if( -d $full) { my @morefiles = recursive_filelist($full); push(@files, @morefiles); } elsif (-f $full) { push(@files, $full); } } return @files; }

20041118 Janitored by Corion: Changed PRE tags to CODE tags as per monastery convention

Replies are listed 'Best First'.
Re: perl filenames and square brackets
by Fletch (Bishop) on Nov 18, 2004 at 18:19 UTC

    One, square brackets are significant to glob just as they are to most UNIX shells (e.g. foo[abc] meaning match any of the files fooa, foob, or fooc), so you'll need to escape them with backslashes. Two, see File::Find or File::Find::Rule rather than reinventing the wheel.

    Addendum: And you should test if something's a directory (see -d in perldoc -f -X) before trying to recurse down into it anyway.

Re: perl filenames and square brackets
by etcshadow (Priest) on Nov 18, 2004 at 18:57 UTC
    All above is correct. While you're better off, overall, changing the whole algorithm to using some File::Find variant, the simplest most direct solution to the problem, is to just replace the glob with an opendir, readdir combo. So, rather than:
    $dir .= '*'; my @list = glob($dir);
    you could do:
    opendir(DIR, $dir) or die $!; my @list = readdir(DIR) or die $!; closedir(DIR) or die $!;
    So that you're actually looking at the file contents, directly, rather than relying on globbing.
    ------------ :Wq Not an editor command: Wq
Re: perl filenames and square brackets
by jimbojones (Friar) on Nov 18, 2004 at 18:28 UTC
    Hi

    Are the square-brackets in a directory name? When you recurse into that directory, I suspect glob will interprete the [] in the file path as a character class (I think), not as the path name. You would need to escape.

    However, you're better off using a module for this. File::Find is a good place to start, although it's a bit weird in its calling convention. The following node details why this type of recursion can be a bad thing: 18101, and also details how things can go back and forth here in the Monastery {grin}

    - j