in reply to Testing for a directory handle

G'day ns550,

If you attempt to use telldir on an invalid directory handle, you'll get a "telldir() attempted on invalid dirhandle" warning (see perldiag). You can promote that warning to an error with FATAL (see the warnings pragma). That error can now be captured and tested.

I created some test files:

$ ls -al pm_1208018_test_dir* pm_1208018_test_dir: total 0 drwxr-xr-x 3 ken staff 102 Jan 30 07:08 . drwxr-xr-x 20 ken staff 680 Jan 30 07:43 .. -rw-r--r-- 1 ken staff 0 Jan 30 07:08 pm_1208018_test_file pm_1208018_test_dir_closed: total 0 drwxr-xr-x 2 ken staff 68 Jan 30 07:40 . drwxr-xr-x 20 ken staff 680 Jan 30 07:43 .. pm_1208018_test_dir_empty: total 0 drwxr-xr-x 2 ken staff 68 Jan 30 07:29 . drwxr-xr-x 20 ken staff 680 Jan 30 07:43 ..

I used a standard alias of mine:

$ alias perle alias perle='perl -Mstrict -Mwarnings -Mautodie=:all -E'

I started with a simple, one-liner test. I then added more and more tests: the result wrapped around four lines. Here it is; expanded for ease of viewing. I've also annotated the output in situ.

$ perle ' open my $fh, "<", "pm_1208018_test_dir/pm_1208018_test_file"; opendir(my $dh, "pm_1208018_test_dir"); opendir(my $eh, "pm_1208018_test_dir_empty"); opendir(my $ch, "pm_1208018_test_dir_closed"); closedir $ch; my $nh = "42"; my $uh; my %h = (fh => $fh, dh => $dh, nh => $nh, eh => $eh, uh => $uh, ch + => $ch); for (keys %h) { use warnings FATAL => "io"; eval { my $x = telldir $h{$_}; say "$_ is a dirhandle"; 1 } or say "$_ is not a dirhandle" } ' fh is not a dirhandle # fh = filehandle nh is not a dirhandle # nh = not a handle (just the number 42) eh is a dirhandle # eh = dirhandle to "pm_1208018_test_dir_empty +" dh is a dirhandle # dh = dirhandle to "pm_1208018_test_dir" ch is not a dirhandle # ch = closed handle uh is not a dirhandle # uh = undefined handle (declared but uninitia +lised)

[Note that "pm_1208018_test_dir_empty" isn't technically empty. On *nix machines it shows the "." and ".." entries. I'm not sure how that works on MSWin. I've left it in as a potential edge case.]

— Ken

Replies are listed 'Best First'.
Re^2: Testing for a directory handle
by syphilis (Archbishop) on Jan 30, 2018 at 01:10 UTC
    If you attempt to use telldir on an invalid directory handle, you'll get a "telldir() attempted on invalid dirhandle" warning

    Also, telldir returns undef in such a case, so I'm thinking we could alternatively just test for definedness:
    C:\_32>perl -le "open D, '<','test.txt' or die $!; print 'dir' if defi +ned telldir D; print 'DONE';" DONE C:\_32>perl -le "opendir D, 'comp' or die $!; print 'dir' if defined t +elldir D; print 'DONE';" dir DONE
    Of course, if it turns out that telldir was given something other than a handle, then it's a fatal error:
    C:\_32>perl -le "open D, '<','test.txt' or die $!; print 'dir' if defi +ned telldir $x; print 'DONE';" Bad symbol for dirhandle at -e line 1.
    So that scenario would need to be avoided.

    On *nix machines it shows the "." and ".." entries

    Yes, it's the same on Windows.

    Cheers,
    Rob
      "Yes, it's the same on Windows."

      Thanks for that. I had a feeling it might have been the same but wasn't sure. It's been many years since I've written any code to interact with a MSWin filesystem.

      — Ken

Re^2: Testing for a directory handle
by afoken (Chancellor) on Jan 30, 2018 at 23:09 UTC
    On *nix machines it shows the "." and ".." entries. I'm not sure how that works on MSWin. I've left it in as a potential edge case.

    Well, as usual for Microsoft software: Don't expect consistent behaviour. Most directories have the . and .. entries. For the root directory of any drive, it heavily depends on the drive type. Some root directories have the . and .. entries, others don't. See Re^6: readdir() on a sysopen() handle? for details.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      Thanks for the additional information regarding this. It doesn't affect me personally (either at work or home) at the moment, and probably won't do in the forseeable future; however, for those working with the MSWin filesystem, this could be important.

      I suppose the real issue is how this might affect telldir in the context of the code I posted. I'm not in a position to test this but I'll attempt to paraphrase in *nix parlance. Given a truly empty directory (root or otherwise), e.g.

      $ ls -al fred ls: cannot access 'fred': No such file or directory $ mkdir fred $

      Where a listing showed

      $ ls -al fred total 0 $

      instead of

      $ ls -al fred total 0 drwxr-xr-x 2 ken staff 68 Jan 31 12:57 . drwxr-xr-x 18 ken staff 612 Jan 31 12:57 .. $

      How would the "eh" handle be reported? Just to be clear, that's the one I showed as:

      eh is a dirhandle       # eh = dirhandle to "pm_1208018_test_dir_empty"

      If someone could test that and report their findings, it could provide useful information to anyone wanting to use this technique in the future.

      — Ken

Re^2: Testing for a directory handle
by ns550 (Novice) on Jan 29, 2018 at 23:38 UTC

    Cool, good thinking

    I will keep these work-arounds in mind when I am coding

    Thanks, Matt

      If you do find this general technique useful, I'll just highlight two sections from the warnings pragma documentation which you may want to look at:

      Category Hierarchy
      The "io" category has seven sub-categories. Depending on what you're actually doing, you may find these useful for more specific tests.
      Fatal Warnings
      This discusses various caveats with making warnings fatal. It also shows how turn them back to their original non-fatal state.

      — Ken