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

Hi, Is their a way to make file operations in Perl on Unix case insensitive? For example if a file name is "abc". On windows -f "abc" and -f "ABC" would both return true if the file "abc" exist. Since Unix is case sensitive, -f "ABC" would return false. The only way I can think of is doing something like this
sub fileExists { my $dir = shift; my $file = shift; opendir DIR, $dir; my ($exists) = grep /$file/i, readdir DIR; closedir DIR; return $exists; }
I was wondering if their is a cleaner way or if their is a way to tell perl internally to handle all files in a case insensitive maner? Thanks, Alana

Replies are listed 'Best First'.
Re: case insensitive file operations
by wog (Curate) on Sep 19, 2001 at 23:38 UTC
    There is no cleaner easy way. In general, the cleanest solution is to change your perl program to deal with case sensitive file systems correctly, and just generally program portably. See also perlport.

    Note that a -f does not test for file a exsitence alone -- it also checks if it's a "regular" file (not a directory, device, pipe, etc.) (If you want to test for file exsitence, alone, that would be -e.) Also, note that your regex does not match the way you think it does.

    1. it will match parts of a string. So a file called "test1" will be said to exsit by it if a file called "test10" exsits,
    2. metacharacters are not escaped, so "." will not mean the "." character itself but any character (except newline) when matching filenames.
    You could fix these problems with using a regex, but your are probably better off using either lc or uc and eq, e.g.: my($exsits) = grep { lc($file) eq lc($_) } readdir DIR

Re: case insensitive file operations
by Zaxo (Archbishop) on Sep 20, 2001 at 01:26 UTC

    Generally, it is best to be precise about path names.

    Some shells can native glob in a case-insensitive way. shopt -s nocaseglob will set that up in bash. Perl's glob is standalone and does not honor bash options. This approach using backticks will be tricky and not very portable.

    A perl approach:

    sub fileExists { my $dir = shift; my $file = shift; # case insensitive grep on filenames my @exists = grep { lc("$dir/$file") eq lc($_) } glob($dir/*); # returns an array, you want to know if more than one file matches }
    This kind of handling is a spot case. It does not set up any global case insensitivity in perl.

    After Compline,
    Zaxo

Re: case insensitive file operations
by suaveant (Parson) on Sep 19, 2001 at 23:39 UTC
    I really don't think so, since on unix case really does matter, and there could be many different files of the same name, with different case... might be best to go through your dir and lowercase all the file names at the beginning of your code, since you don't care about case...

                    - Ant
                    - Some of my best work - Fish Dinner

Re: case insensitive file operations
by Rhandom (Curate) on Sep 20, 2001 at 01:39 UTC
    Well, this is a hack, but...

    #! /usr/bin/perl ### make some files my @dirs = qw(pAuLs PaULs pauls); mkdir($_,0755) for @dirs; my $name="PauLS"; ### all the work $name=~s/(\w)/[\l$1\u$1]/g; my @list = map{ chomp; $_ } `ls -d $name`; ### show what we got print "[".join("][",@list)."]\n"; ### remove the dirs rmdir($_) for @dirs;


    Well, you had to fork, and you get a list back rather than a single file, but, it is case insensitive. I think your better off doing the opendir and living with it (as that is what the ls probably did anyway).

    my @a=qw(random brilliant braindead); print $a[rand(@a)];