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

Hello all,

I am using ActiveState Perl 5.8.8 and File::Find to get a listing of all files on a mapped network drive in Windows XP. However, the program runs for awhile then dies with this error:

Can't cd to j:/AAA/Bargleblasters/Blued wrangler and confluenced switchbacks copies are filed with another cheese/BB mashed/ss-wwwwww tartan/1234 AS Quince/1DD LKu & Dogs & References/1 GH ASDFd/KCOES CVBND/4 is spring 2232 BFGH Vicarsd/11-1 Confusications/22-3-2 JJJJJ../.. at C:/Perl/lib/File/Find.pm line 940.

Is there a way to catch this error, so the program can continue? It's not a matter of user rights; I can cd to the location normally and read the files in it. I am curious if maybe the length of the path comes into play (IIRC, there's only so much you can handle via network as opposed to a physical drive path)

Any guidance would be appreciated. Here's my code:

#!/perl/bin/perl use strict; use warnings; use File::Find; find(\&wanted, ('j:', 'k:', 'l:', 'm:')); sub wanted { if ($File::Find::name =~ m/lnk$/i) { warn("Cannot process $File::Find::name: Shortcut\n"); } elsif (-f $File::Find::name) { print($File::Find::name, "\n"); } else { warn("Cannot process $File::Find::name: Directory or unknown t +ype\n"); } }

Update (for samtregar): The directory in question has two files in it, and no directories (none named '..', '../..', or any other funny business)

Replies are listed 'Best First'.
Re: Is there a way to catch an error within a module?
by BrowserUk (Patriarch) on Mar 17, 2008 at 17:28 UTC

    For most file and directory handling Win32 APIs, there are two variants. Those with the A suffix (for ANSI character set) and those with a W suffix (for Wide character set). Eg. FindFirstFileA(...) & FindFirstFileW( ... ).

    Perl is usually built to use the A suffix variants, and they have a built in limitation, on the length of paths, of 260 characters. The path in your error message is 262 characters.

    Options:

    1. Try and build your own version of Perl having enable defined the macro USING_WIDE().

      I don't think anyone has tried this for a long time. I'm not sure that the implementation was very complete when it was working.

      A quick grep of the 5.10.0 sources suggests that all the support that did exist at 5.8.6 has been stripped out.

    2. Take the people that created those ridiculous paths out the back and shoot them.

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Thanks for the information, though the options seem pretty bleak.

      Option 1, from your post, seems like a non-starter. Option 2, while BOFH-ly tempting, isn't likely either. The best I can do is rename them as I find them.. but given that this is a rather large filesystem, doing this onesy-twosy is going to be painful. At least I know what I'm in for..
        but given that this is a rather large filesystem, doing this onesy-twosy is going to be painful.

        Just type tree /a f: > tree.txt at a command line and go get a coffee. When you come back load the file into your editor and you'll quickly see what needs to be done.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      MAX_PATH is the same for both

        Wrong! From the docs for FindFirstFile:

        In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 widecharacters, call the Unicode version of the function and prepend "\\?\" to the path. For more information, see Naming a File.

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Is there a way to catch an error within a module?
by igelkott (Priest) on Mar 17, 2008 at 18:43 UTC
    Is there a way to catch this error, so the program can continue?

    File::Find can preprocess a folder and it can be told to skip chdir. I couldn't reproduce your error so here's an example of using both directives (with your code as a template).

    #!/perl/bin/perl use strict; use warnings; use File::Find; my $longdir = 250; find( { wanted => \&wanted, preprocess => \&prep, no_chdir => 1 }, ('j:', 'k:', 'l:', 'm:')); sub wanted { if ($File::Find::name =~ m/lnk$/i) { warn("Cannot process $File::Find::name: Shortcut\n"); } elsif (-f $File::Find::name) { print($File::Find::name, "\n"); } else { warn("Cannot process $File::Find::name: Directory or unknown t +ype\n"); } } sub prep { return length $File::Find::dir > $longdir ? () : @_; }

      Thanks for this.. I'm trying it now. I'll let you know if it works out.

      Update: This at least allowed the error to be skipped over, so thanks! Now to correct some users.. or at least their paths.

Re: Is there a way to catch an error within a module?
by rir (Vicar) on Mar 17, 2008 at 18:45 UTC
    Judging by the info given in this thread, looks like an buffer overflow bug in File::Find. Appending "/.." when it should not.

    Catching errors in Perl is done with the block form of eval. Something like:

    eval { code_that_dies; } if ( $@ ne '' ) { code_to_recover_from_code_that_dies; }
    There are modules to sugar the syntax; search for "error" and "exception" on CPAN.

    Be well,
    rir

      This is not buffer overflow
Re: Is there a way to catch an error within a module?
by samtregar (Abbot) on Mar 17, 2008 at 17:14 UTC
    Is ".." actually the name of the last directory in that path? If so, I bet that's your problem! Length also seems like a likely cause - that path is 262 characters long, which may make it the first one over 255 in your search. You might test that assumption by creating a test directory tree with paths of various lengths over and under the limit.

    -sam

      I updated my original message to answer your question. I'll have to test for the directory length problem, but it does let me 'cd' and 'dir' correctly, so Windows does not seem to have an obvious issue with it.