4

Consider the following code:

print cwd . "\n";
$str= "../source"; # note the lower case 's'    
chdir($str);
print cwd . "\n";

If my current directory is c:\parentdir\Source (note the capital 'S'), the output of this will be:

c:/parentdir/Source
c:/parentdir/source

This causes problems in a subroutine of mine that cares about the correct case of folder names. $str is passed in to my subroutine, so I can't know ahead of time whether it has the correct case. How do I determine the case-correct name of a path that matches $str?

More detail here:

  • I realize that ../source is a pathological example, but it serves to illustrate the problem. It occurs even if $str is requesting a folder other than the current one.
  • I have tried numerous options, including rel2abs, a glob search on $str, and others, but they all seem to return "source" instead of "Source".
  • I could search $str/.. for all directories, convert them all to absolute paths and compare them to an absolute path version of $str, but that seems like a hack. I was hoping for something more elegant.
Craig
  • 855
  • 1
  • 9
  • 14
  • It's not incorrect. Usually Windows filesystems are case-insenstive, unless NTFS is configured otherwise. – m0skit0 Nov 03 '11 at 12:50
  • Absolutely true. Unfortunately, my subroutine needs the correct case for reasons other than simply manipulating the file system. So, while Windows and Perl don't care, I unfortunately have to. – Craig Nov 03 '11 at 14:12
  • Case-insensitive, yes, but it is also *case-preserving*. If a file is created as `Foo`, it can be accessed using `foo`, but the system knows its name is `Foo`. – ikegami Nov 03 '11 at 19:07

2 Answers2

10
#!/usr/bin/perl

use warnings; use strict;
use Cwd;
use File::Spec::Functions qw( canonpath );
use Win32;

print canonpath( cwd ), "\n";

chdir '../source';

print canonpath( cwd ), "\n";

print canonpath( Win32::GetLongPathName( cwd ) ), "\n";
C:\DOCUME~1\...\LOCALS~1\Temp\t\Source> t
C:\DOCUME~1\...\LOCALS~1\Temp\t\Source
C:\DOCUME~1\...\LOCALS~1\Temp\t\source
C:\Documents and Settings\...\Local Settings\Temp\t\Source
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
  • Thank you! It looks to me like I don't even need canonpath. If I issue the following: $str = Win32::GetLongPathName($str);, then it seems to change to the correct case, even if $str specifies a relative path. – Craig Nov 03 '11 at 14:24
  • 1
    `canonpath` is just to get Windows style slashes in paths in case that mattered. – Sinan Ünür Nov 03 '11 at 14:24
0

I use cygwin and svn, and I found this question when svn couldn't find that the files because it was case sensitive

e.g. $ cd /cygdrive/c/svn/delphi2010/lib/checksum # not the true case

$ svn ls svn: warning: W155010: The node '/cygdrive/c/svn/delphi2010/lib/checksum' was not found. svn: E200009: Could not list all targets because some targets don't exist

$ eval cd $( cygpath $( perl -le 'use Win32; $d=cygpath -aw .; chomp($d); print Win32::GetLongPathName($d)' ) )

$ pwd /cygdrive/c/svn/Delphi2010/lib/CheckSum # note the case is restored

and svn ls works again!

David Dyck
  • 130
  • 1
  • 6