http://www.perlmonks.org?node_id=684408

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

I was wondering what the best way is to handle case insensitive file systems.

On a *nix filesystem I want to open either File or FILE or throw an error if they both exist.

On Windows and Darwin this fails, as both files always exist, but are the same file.

I am looking for suggestions on the best way to handle this problem.

UPDATE: Spelling was ruff. Thanks Albannach

-- gam3
A picture is worth a thousand words, but takes 200K.

Replies are listed 'Best First'.
Re: Case insensitive Filesystems.
by ww (Archbishop) on May 04, 2008 at 14:20 UTC

    Two nits for the price of one:

    On a *nix filesystem I want to open either File or FILE or throw an error if they both exist.

    Do you really want to "throw an error" or do you mean "be alerted to the existence of two files with similar names?" The names may be similar, but the content need not be identical. (And -- not a nit; just curiousity: do you care about whether the two are in the same path?)

    On Windows and Darwin this fails, as both files always exist, but are the same file.

    At least on 'doze, IMO that's a misleading statement:

    Only ONE such file exists, but because w32 is case-insensitive-but-case-preserving any attempt to create "FILE" in a particular \path\to\dir\ which already contains "File" will (for some aps) produce a (windows-rooted) warning "File already exists; overwrite?" or (windows-native) error message that "Duplicate name exists...".

    Sidebar: At least some aps which automaticly create/overwrite a .bak file on save, will create (in the example above) the .bak as "FILE.bak" (case transformed to match the new name).

Re: Case insensitive Filesystems.
by BrowserUk (Patriarch) on May 04, 2008 at 14:37 UTC

    If you need to know the actual casing of the name, Win32::GetLongPathName( ) will give it to you on Win32:

    print "$_ : ", Win32::GetLongPathName( $_ ) for qw[ file filE FILE Fi +le ];; ## In Out file : fIlE filE : fIlE FILE : fIlE File : fIlE

    This is a core function on Win32.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Case insensitive Filesystems.
by swampyankee (Parson) on May 04, 2008 at 15:57 UTC

    One question: do you have specific file names to check or are you looking to see if a given directory has two file names which differ only in case?

    In either case, I'd just open (with opendir) and read (using readdir) the directory of interest. In the first, I'd just do something like this:

    if(scalar( grep { /^$infile$/i } readdir<$dirname>) > 1) { raise_a_flag(); }
    and in the second, I'd walk through the readdir output and use a hash, with the upcased or downcased file name as the hash key, and raise a flag when there is a duplicated key.

    Warning:  example code only. Almost certainly guaranteed not to work.


    Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Re: Case insensitive Filesystems.
by Cody Pendant (Prior) on May 04, 2008 at 12:34 UTC
    Use the variable $^O to see which operating system you're on before you do it?


    Nobody says perl looks like line-noise any more
    kids today don't know what line-noise IS ...

      That is insufficient as operating systems may mount foreign filesystems.

      Good Day,
          Dean

      In addition to what duelafn said, it was also pointed out in an earlier thread by Fletch...

      $^0 returns what OS perl was built on... not on what it's running.

      See this node: Re^2: OS400 Pace - architecture?

      regexes


      -------------------------
      Nothing in the world can take the place of persistence. Talent will not; nothing is more common than unsuccessful men with talent. Genius will not; unrewarded genius is almost a proverb. Education will not; the world is full of educated derelicts. Persistence and determination are omnipotent. The slogan "press on" has solved and always will solve the problems of the human race.
      -- Calvin Coolidge, 30th President of the USA.
Re: Case insensitive Filesystems.
by igelkott (Priest) on May 04, 2008 at 12:41 UTC

    Even with a "case-preserving" OS like windows (NT+), you should be able to readdir and check the names that way.

Re: Case insensitive Filesystems.
by educated_foo (Vicar) on May 04, 2008 at 13:58 UTC
    Look at the files' inodes, i.e. (stat $file)[1]
Re: Case insensitive Filesystems.
by jonnyfolk (Vicar) on May 04, 2008 at 12:31 UTC
    I'm wondering if you could use File::Find to extract a list of files in the directory and perform a test on the list to discover what's in there. You can then perform you actions on the basis of those tests?

      Hi,

      It's better to use some hashing like Digest::MD5 to see if the files are the same.

      Regards,

      fmerges at irc.freenode.net