Using Perl on Windows, how can I ensure I get the path in the correct case following a chdir?
-
20-02-2021 - |
Question
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.
Solution
#!/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
OTHER TIPS
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