in reply to Re^2: getting a few simple scripts to work on windows
in thread getting a few simple scripts to work on windows
Okay, since you're asking questions, I'm trying to re-familiarize myself with it; that was all Oct of last year, and I hadn't thought about it since. ...
The isjunc() and is_junction() are effectively two different ways for testing for whether a file is a junction. The isjunc() is a much simpler way of doing it -- it doesn't require spawning to the shell's dir /AL /B, and is (presumably) much more efficient. If you comment out just the f32attr call in my example script, you can see that is_junction (which results in a capital J in the printout) and isjunc (which results in a lower-case j) both trigger on the same files. Basically, with that, I was trying to prove to myself that isjunc really found all the junctions. (I knew that windows dir should, so was comparing it as "golden" to my "experimental" isjunc.) Specific answers to your questions in the readmore...
Q1 Where does the code for the is_junc and f32attr subs go?
In the script which is using File::Find, I just add the lines
#### https://metacpan.org/pod/Win32API::File use Win32API::File qw'GetFileAttributes :FILE_ATTRIBUTE_'; sub isjunc { return GetFileAttributes($_[0]) & FILE_ATTRIBUTE_REPARSE_POINT }
The f32attr was just a debug function, and is not needed. Similarly, I don't use the older is_junction() or its helper list_junctions() which shelled out, either, since they were just verifying that I could get accurate junction-identification. All that is needed for a junction test is the injunc listed above.
Q3) What is the simplest way to test whether a file is a junction, and if it is, simply ignore it whilst recursing through the rest of them?
In my wanted() function (which is what gets passed to the File::Find::find() call), I have a section which says
if ( -d ) { # junctions show up as TRUE for `-d` if( isjunc($File::Find::name) ) { # if it's a junction, don't bother creating checking desti +nation directory existence, # and don't try to recurse into it $File::Find::prune = 1; printf ("[%s] %-12s'%s'\n", scalar(localtime), "JUNCTION:" +, $File::Find::name) if ($VERBOSE); return; } ... # go do the stuff I want to do if it's a real directory, a +nd not a junction }
The $File::Find::prune is documented in File::Find as the way to prevent recursing into that directory (or junction)
Q2 Am I correct to surmise that File::Find is essentially broken for windows? (Others may say windows is broken without the point being different.)
I disagree with that assessment. It doesn't have an ideal handling of junctions -- it just prints a warning, but otherwise cannot do anything with the junction -- but other than that, it works fine in windows... and even with junctions, it just gives a warning, so it continues to effectively work. Thus, arguably buggy, but not effectively broken. (Junctions, IMO, are B.A.D., but that's windows' fault, not File::Find's fault. And while it might have been nice if File::Find could recurse into the junction, the warning-only result is at least a "do-no-harm" response to the strange junction.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: getting a few simple scripts to work on windows
by Aldebaran (Curate) on Aug 16, 2019 at 06:09 UTC | |
by Aldebaran (Curate) on Aug 21, 2019 at 17:51 UTC |