Opening a file with case-insensitive name

J

Jason Carlton

Let's say that I have a script that allows the user to manually type
in the file name that they want to open. It would go something like
this:

$filename = param('filename');

open FILENAME "/home/mydomain/$filename" or die;
<do whatever...>
close FILENAME;


(Please overlook any typos above; it's just an example for the sake of
clarity, and not important.)

The question is, what if the file name is "MyFile.txt", but they type
"myfile.txt", "MYFILE.TXT", "mYfILE.txt", or something similar. Is
there a way to open the file and ignore the case of the file name?

Ideally, all of the files would have been saved in lower case, then I
could just lc($filename) and be done with it. But I'm inheriting this,
and what's done is done. I could probably change all of the filenames,
but I'm hoping there's a coding option that would make it unnecessary.
 
J

Jack

Jason Carlton said:
Let's say that I have a script that allows the user to manually type
in the file name that they want to open. It would go something like
this:

$filename = param('filename');

open FILENAME "/home/mydomain/$filename" or die;
<do whatever...>
close FILENAME;


(Please overlook any typos above; it's just an example for the sake of
clarity, and not important.)

The question is, what if the file name is "MyFile.txt", but they type
"myfile.txt", "MYFILE.TXT", "mYfILE.txt", or something similar. Is
there a way to open the file and ignore the case of the file name?

Ideally, all of the files would have been saved in lower case, then I
could just lc($filename) and be done with it. But I'm inheriting this,
and what's done is done. I could probably change all of the filenames,
but I'm hoping there's a coding option that would make it unnecessary.

1. Get a listing of your directory contents (i.e. filenames) and store them
in an array (or hash).
2. Do a case insensitive comparison on the variable to see if it matches any
filename.
3. Open the file using the proper filename.

The easier way is to change your input to a controlled environment using a
listbox selection or a drop-down entry where "you" control the file names.

Jack D.
 
J

Jürgen Exner

Jason Carlton said:
open FILENAME "/home/mydomain/$filename" or die;
<do whatever...>
close FILENAME;

The question is, what if the file name is "MyFile.txt", but they type
"myfile.txt", "MYFILE.TXT", "mYfILE.txt", or something similar. Is
there a way to open the file and ignore the case of the file name?

That depends upon your operating/file system. All (newer) Windows file
systems are case-preserving, but still case-insensitive, i.e. "it would
just work". Your sample file names with the ending txt (in different
capitalization) seem to indicate that you are using some sort of
Windows.
Ideally, all of the files would have been saved in lower case, then I
could just lc($filename) and be done with it. But I'm inheriting this,
and what's done is done. I could probably change all of the filenames,
but I'm hoping there's a coding option that would make it unnecessary.

If you are on a file/operating system that is case-sensitive you could
read the directory and create a hash from it, using the normalized form
of the file name as the key and the original form as the value.
Then you could simply say

open FILE, $dirhash{normalize($userstring)} ......

jue
 
J

Jason Carlton

That depends upon your operating/file system. All (newer) Windows file
systems are case-preserving, but still case-insensitive, i.e. "it would
just work". Your sample file names with the ending txt (in different
capitalization) seem to indicate that you are using some sort of
Windows.

Sorry, that was my mistake. I'm running it on Linux, and didn't think
about the extension meaning anything.

If you are on a file/operating system that is case-sensitive you could
read the directory and create a hash from it, using the normalized form
of the file name as the key and the original form as the value.
Then you could simply say

        open FILE, $dirhash{normalize($userstring)} ......

OK, that'll work. It's not perfect, since there are about 60,000 files
to consider (which is why I don't put them in a drop menu, as Jack
suggested), but it should hold over for now. Eventually I'll set up an
Ajax system to cope with it.

Thanks, all,

Jason
 
M

Martijn Lievaart

Let's say that I have a script that allows the user to manually type in
the file name that they want to open. It would go something like this:

$filename = param('filename');

open FILENAME "/home/mydomain/$filename" or die;
<do whatever...>
close FILENAME;


(Please overlook any typos above; it's just an example for the sake of
clarity, and not important.)

The question is, what if the file name is "MyFile.txt", but they type
"myfile.txt", "MYFILE.TXT", "mYfILE.txt", or something similar. Is there
a way to open the file and ignore the case of the file name?

Ideally, all of the files would have been saved in lower case, then I
could just lc($filename) and be done with it. But I'm inheriting this,
and what's done is done. I could probably change all of the filenames,
but I'm hoping there's a coding option that would make it unnecessary.

untested:

my $realfilename = grep { lc($filename) eq lc($_) }
glob('/home/mydomain/*');

HTH,
M4
 
J

John W. Krahn

Martijn said:
untested:

my $realfilename = grep { lc($filename) eq lc($_) }
glob('/home/mydomain/*');

That won't work as glob() returns the complete path, and grep returns
the number of matches in scalar context, not the file name(s). Should
work as:

my @realfilenames = grep lc eq lc "/home/mydomain/$filename", glob
'/home/mydomain/*';



John
 
B

Brian Wakem

John said:
I would suggest to read all files in /home/mydomain/, lowercase all
entries, and match it with the lowercase version of $filename.


One potential gotcha here is that lowercasing all the files in the dir could
leave you with more than 1 file with the same name. What is the OP going
to do then I wonder?
 
J

John Bokma

Brian Wakem said:
One potential gotcha here is that lowercasing all the files in the dir could
leave you with more than 1 file with the same name. What is the OP going
to do then I wonder?

Oops, very good point.
 
J

Josef

Am 17.12.2009 08:36, schrieb John W. Krahn:
Martijn said:
[…] The question is, what if the file name is "MyFile.txt", but they type
"myfile.txt", "MYFILE.TXT", "mYfILE.txt", or something similar. Is there
a way to open the file and ignore the case of the file name? […]
my @realfilenames = grep lc eq lc "/home/mydomain/$filename", glob
'/home/mydomain/*';

Better
my $filename='bLaBlA.Txt';
(my $filepat=$filename) =~
s{(.)}
{ local $_=$1;
(uc ne lc) ? "[\U$_\L$_]" :
/[[\]{}\s]/ ? "\\$_" : $_ # or /[[\]{}\s*?]/
}ge;
my @filematches=glob($filepat);
my $mostlikely=exists $filematches[0] ? $filematches[0] : undef;

print join(',',@filematches)." from $filepat\n"
# BlaBla.txt from [Bb][Ll][Aa][Bb][Ll][Aa].[Tt][Xx][Tt]

The wildcards * and ? are allowed for the user.
If this is not desirable, than this chars can be added to the inner RE.

I expect that this solution is faster as the previous.

Another solution was presented from Jürgen (hash as cache).
His solution needs IHMO more time at startup for building the hash,
but the following searches should be faster.

Just guessing.

best regards & sorry for my bad english,
Josef
 
S

sln

Sorry, that was my mistake. I'm running it on Linux, and didn't think
about the extension meaning anything.



OK, that'll work. It's not perfect, since there are about 60,000 files
to consider (which is why I don't put them in a drop menu, as Jack
suggested), but it should hold over for now. Eventually I'll set up an
Ajax system to cope with it.

Thanks, all,

Jason

The question is, what if the file name is "MyFile.txt", but they type
"myfile.txt", "MYFILE.TXT", "mYfILE.txt", or something similar. Is
there a way to open the file and ignore the case of the file name?

Except that:

@dir = ('MyFile.txt', 'mYfile.Txt', 'myfilE.txT');
$input = 'myfile.txt';

There seems no choice but to conclude that there is no
file named 'myfile.txt'.

-sln
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top