Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Inelegant code to compare file names

by davies (Prior)
on Sep 21, 2011 at 19:30 UTC ( [id://927209]=perlquestion: print w/replies, xml ) Need Help??

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

TIMTOWTDI, in Excel as in Perl. Excel usually has two ways of doing anything. What gets my goat is that those two ways are usually utterly incompatible.

When processing Excel files with Win32::OLE, I always create an instance of Excel in my Perl code, and strongly recommend this practice. Unfortunately, this does not stop Excel opening files itself before any files the user designates - add-ins would fall into this category. This means that the Perl instance of Excel may have several files open.

Excel's next quirk is that the filename it holds in the VBProjects collection may well be different from the filename given by the user. There are three main causes of differences. The first is that the user may not have specified a directory. Excel will add a fully qualified path. The second is that the user may not have specified an extension. He knows, after all, that the file has no extension. Windows tells him this. No-one has mentioned the option to hide extensions for registered file types, which means that he never sees ".xls". The third is that he may be using a mapped network drive. This Excel will convert from the mapped name to an unmapped, fully qualified name.

The following code is my attempt to compare two file names in these different formats. It works for everything I've tried, but I'm sure that there is a better way, probably involving regexes.

use strict; use warnings; my $f1 = 'z:\proj\proj'; my $f2 = '\\192.168.1.3\server\proj\proj.ext'; my $s1 = substring($f1); my $s2 = substring($f2); if ($s1 eq $s2) { print "Matched $s1\n"; } else { print "Main bus B undervolt - $s1 <> $s2\n"; } sub substring { my $file = shift; my $back = rindex($file, "\\"); my $dot = rindex($file, "."); if ($dot > $back) { return substr($file, $back + 1, $dot -$back - 1); } else { return substr($file, -(length($file) -1 -$back)); } }

Any advice would be appreciated, especially pointers to further reading. The intention of the code is to take everything after the last backslash (if there is one) up to the last dot (if there is one after the last backslash) and to compare this for each string.

TIA & regards,

John Davies

Update: a /msg has pointed out (correctly AFAICT without more extensive testing) that launching Excel with the /s option prevents loading of add-ins and personal.xls. There are other ways of loading files, such as VBA references, that I haven't tested. My fear on this is that there are some ways to drag files into an instance somewhere in the depths of Excel (possibly versions yet to be released) that I haven't met.

Replies are listed 'Best First'.
Re: Inelegant code to compare file names
by Eliya (Vicar) on Sep 21, 2011 at 20:40 UTC
    The intention of the code is to take everything after the last backslash (if there is one) up to the last dot (if there is one after the last backslash)

    You could extract that 'proj' fragment from the paths something like this (in your substring routine):

    my ($name) = $file =~ /([^\\]+?) # everything but backsla +shes, non-greedy (?:\.[^\\.]*)? $ # optional .ext, anchore +d at the end /x;

    i.e., if there is an extension, the non-greediness of the captured first part lets the extension be matched by the optional second part, so it isn't included in the captured substring.  Otherwise, you simply capture everything-but-backslashes at the end of the path.

    Whether that's more elegant is a matter of personal taste, though.

Re: Inelegant code to compare file names
by RichardK (Parson) on Sep 22, 2011 at 09:27 UTC

    Hi John,

    Would splitpath from File::Spec work to get the file name in your case ? I don't know how it works on windows but I found it's usually easier & gets things right :)

    my ($volume,$directories,$file) = File::Spec->splitpath( $path );
Re: Inelegant code to compare file names
by davies (Prior) on Sep 22, 2011 at 17:17 UTC

    Thank you both for the replies. I've used Eliya's regex as it will make everything that bit shorter. I won't pretend I understand the regex 100%, but that's something I can work on when I have everything working. While I'm sure I could have got the File::Spec solution working, the docs kept talking about Unix and the backslashes Losedows uses have given me enough headaches in the past. Besides, I get the impression from the docs that I would still have to strip the extension out, so I would be using either part of my code or the regex anyway.

    It's not so much about getting working code - I had that anyway - as trying to understand Perl better. I'm still very much a novice, and having the regex to work through will help me advance.

    Thanks again & regards,

    John Davies

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://927209]
Approved by keszler
Front-paged by chrestomanci
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (7)
As of 2024-04-19 14:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found