Re: Unexpected file test (-f) result on Windows
by BrowserUk (Patriarch) on Sep 19, 2003 at 14:10 UTC
|
See perlfunc:-X where it says:
This unary operator takes one argument, either a filename or a filehandle, and tests the associated file to see if something is true about it.
In essence, what you are passing is not a filename (or a filehandle). If you remove the '<' and '>>', you'll then get the results you are hoping for.
As it is, you are asking perl to look for a file called '< file' or '>> file', which probably don't exist, so there for they cannot be ordinary files, so the test fails, which is how it should be.
The use of '< file' in the two ar form of open is unique (and only applicable) to that call, where it serves to not only name the file, but also specify the mode of opening the file.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.
| [reply] |
|
|
BrowserUk wrote:
In essence, what you are passing is not a filename (or a filehandle). If you remove the '<' and '>>', you'll then get the results you are hoping for.
I do understand what you are saying here. However, I'm not trying to have the file test succeed based on open's specical semantics, but rather I'm trying to _detect_ whether somebody else is trying to use open's 2 arg semantics with my module. I fully expect the file test to fail if somebody tries to use, for example, '>>testfile.log' as an argument to my module's 'new()' or 'open()' methods.
(Does that make sense?! :-) )
The use of '< file' in the two ar form of open is unique (and only applicable) to that call (open)...
This was my point! :-) As far as I knew, the only place where one was allowed to use the magic semantics of the first argument to 'open', is in the first argument to open!
However, for some weird reason, on Windows, a file test on '<testfile.log' (or '<<testfile.log', or even '<<<<<<<<testfile.log') returns true. However, I have just done some more digging, and I think it is a problem with Windows, rather than Perl.
C:\>perl -e "my $f=qq(<testfile.log); print ref($f); if (-f $f) { prin
+t qq(AS thinks this is a file\n); }"
AS thinks this is a file
C:\>dir "<testfile.log"
Volume in drive C has no label.
Volume Serial Number is D0C3-B79D
Directory of C:\
19/09/2003 15:03 0 testfile.log
1 File(s) 0 bytes
0 Dir(s) 1,764,376,576 bytes free
C:\>dir "<<testfile.log"
Volume in drive C has no label.
Volume Serial Number is D0C3-B79D
Directory of C:\
19/09/2003 15:03 0 testfile.log
1 File(s) 0 bytes
0 Dir(s) 1,764,376,576 bytes free
C:\>dir "<<<<<<<<<testfile.log"
Volume in drive C has no label.
Volume Serial Number is D0C3-B79D
Directory of C:\
19/09/2003 15:03 0 testfile.log
1 File(s) 0 bytes
0 Dir(s) 1,764,376,576 bytes free
Looks like this may just be another Microsoft "feature". How helpful of them! ;-)
Cheers, -- Dave :-)
$q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print
| [reply] [d/l] |
|
|
Update: FWIW, this "undocumented feature" is deep within the OS, using '<' in the argument to FindFirstFile/FindNextFile apis also treats it the same way as '*'. It appears that this is the only undocumented character that exhibits this behaviour. Weirdness indeed.
What can I say? Sorry, but I completely misread the sense of your constanation. Your right! It appears that CMD is treating '<' in the same way as '*'
P:\test>dir "<.bak"
Volume in drive P is Winnt
Volume Serial Number is D822-5AE5
Directory of P:\test
27/08/03 00:47 608 286744.pl8.bak
28/08/03 20:20 801 287272.pl8.bak
31/08/03 12:42 729 287900-2.pl8.bak
31/08/03 09:58 1,056 287900.pl8.bak
05/09/03 15:37 2,015 289016-2.pl8.bak
05/09/03 09:56 1,092 289106.pl8.bak
05/09/03 17:26 1,165 289250.pl8.bak
08/09/03 10:49 742 b-sort.pl8.bak
...
I'm really surprised that I have never encountered this behaviour before...but then, I would never have thought to look for it:)
It is weird, as far as I am aware, completely undocumented, and very annoying. I cannot even begin to fathom how and why this would have been done!
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.
| [reply] [d/l] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Why not just untaint the filename you are getting if you consider << >> < > tainted input?
-Waswas
| [reply] |
|
|
|
|
|
|
Re: Unexpected file test (-f) result on Windows
by dws (Chancellor) on Sep 19, 2003 at 15:06 UTC
|
In addition to the symptom you're reporting, you have a precedence problem that you haven't spotted yet.
open FILE, ">testfile.log" ||
die "Unable to create file: $!";
isn't the same as
open(FILE, ">testfile.log") ||
die "Unable to create file: $!";
or
open FILE, ">testfile.log"
or die "Unable to create file: $!";
In the first case, you will never, ever see that die.
In the second and third cases, you will. Consult the Perl operator precedence table in perlop for details.
Further, you can save yourself a lot of confusion by using the three argument form of open. E.g.,
open(FILE, ">", $log) or die "$log: $!";
This allows you to pass around filenames in variables without polluting them with extraneous symbols.
| [reply] [d/l] [select] |
|
|
open FILE, "name" or die "died: $!";
For some inexplicable reason, I used || in this test script!
("Yeah, right, that's what they all say!" shouts somebody at the back of the room...)
Is the last form of open in your examples just a Perl 5.8 construct? I've not seen it used that much (then again, I don't regularly review much code, apart from on PerlMonks).
Cheers, -- Dave :-)
$q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print
| [reply] [d/l] |
|
|
| [reply] |
|
|
Re: Unexpected file test (-f) result on Windows
by shenme (Priest) on Sep 19, 2003 at 14:13 UTC
|
On both AS 5.6.1 and 5.8.0 on WinXP I get the same results. In fact if file README exists, -f "<<<<<<<<<README" returns true! But "< README" returns false, as do combinations with >. | [reply] |
Re: Unexpected file test (-f) result on Windows
by BrowserUk (Patriarch) on Sep 20, 2003 at 01:14 UTC
|
A little more information gleaned by experiment, as I stil have yet to find any documentation on this. MS or otherwise. YAROSF! (Yet Another Redmond-Only Secret Feature!)
After a some more thunking and chundering, I discovered that both '<' and '>' are "special" when used in filenames passed to the Find(First|Next)File() APIs.
- '<' is similar to '*', but its 'wildness' is bounded by '.'s.
Given the files
P:\test\xxx>dir /b
test.test.X
test.test.XX
test.test.XXX
test.test.XXXX
test.test.XXXXX
test.X
test.XX
test.XXX
test.XXXX
test.XXXXX
'test.*" will match them all but 'test.<' will only match
test.X
test.XX
test.XXX
test.XXXX
test.XXXXX
it would require 'test.<.<' t match the rest.
This is somewhat analogous to the behaviour of '.' in a regex matching "\n" (or not) depending upon the precesence or absence of the /s modifier.
- '>' is similar in behaviour to '?'. At first I could find no difference as the wildness of '?' is already limited to not matching '.'s.
Given the set of files above,
- 'test?' and 'test>' will match none of them,
- 'test.?' and 'test.>' will find 'test.x'
- 'test*.?' and 'test*.>' will find 'test.x' and test.test.x'
- 'test>.?' and 'test>.>' will only find 'test.x'
There is a difference but in typical fashion, it is incredibly hard to define. It only seems to come into play when there are two (or more?) '.'s in the wildcard spec. This is a far from comprehensive expose of the possibilities, but unless someone else can find some rhythm or reason to the pattern matching possibilities of this, its going to be like the CLI quoting rules, too damn complex to work out, never mind to try and remember and apply usefully.
In terms of bypassing this 'feature', I think I would opt for something like
$filespec =~ s/(^[<>+|\s]+) | ([<>+|\s]+$)//;
Which I think will deal with any two-arg open adornments without changing the native behaviour or unnecessarily limiting the range of ligitimate filespecs you handle.
It strikes me that it should be left to the calling code to decide if the values they pass in to you should be untainted or not.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.
| [reply] [d/l] [select] |
Re: Unexpected file test (-f) result on Windows
by John M. Dlugosz (Monsignor) on Sep 19, 2003 at 19:10 UTC
|
Windows does not permit these characters in file names:
< > : " / \ |
The slashes are used for separating directory parts, and : is used to separate a stream name, and double-quote avoids having to escape out quotes. So, maybe the left-angle is used for something internally, too, and using that reserved character as part of a file name is conflicting with that.
If I use the \\? prefix to turn off parsing, it seems to treat the < like any other character, but still uses * for a wildcard. | [reply] [d/l] |