Используя Perl в Windows, как я могу гарантировать, что получу путь в правильном регистре после chdir?

#windows #perl #path #case-sensitive #cwd

#Windows #perl #путь #чувствителен к регистру #cwd

Вопрос:

Рассмотрим следующий код:

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

Если мой текущий каталог c:parentdirSource (обратите внимание на заглавные буквы), результат этого будет:

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

Это вызывает проблемы в моей подпрограмме, которая заботится о правильном регистре имен папок. $ str передается в мою подпрограмму, поэтому я не могу заранее знать, имеет ли он правильный регистр. Как мне определить правильное по регистру имя соответствующего пути $str ?

Подробнее здесь:

  • Я понимаю, что ../source это патологический пример, но он служит иллюстрацией проблемы. Это происходит, даже если $str запрашивается папка, отличная от текущей.
  • Я пробовал множество вариантов, rel2abs в том числе поиск по $str глобусу и другие, но все они, похоже, возвращают « source » вместо « Source «.
  • Я мог бы выполнить поиск $str/.. по всем каталогам, преобразовать их все в абсолютные пути и сравнить их с версией абсолютного пути $str , но это похоже на взлом. Я надеялся на что-то более элегантное.

Комментарии:

1. Это не неверно. Обычно файловые системы Windows не зависят от регистра, если NTFS не настроена иначе.

2. Абсолютно верно. К сожалению, моей подпрограмме нужен правильный регистр по причинам, отличным от простого манипулирования файловой системой. Итак, хотя Windows и Perl не заботятся, мне, к сожалению, приходится.

3. Да, без учета регистра, но он также сохраняет регистр . Если файл создан как Foo , к нему можно получить доступ с помощью foo , но система знает, что его имя Foo .

Ответ №1:

 #!/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 ~ 1Temp tSource> t
C:DOCUME ~1...LOCALS ~ 1Temp t Source
C:DOCUME ~1...LOCALS ~ 1Temp t source
C:Documents и Настройки...Local Settings Temp t Source

Комментарии:

1. Спасибо! Мне кажется, что мне даже не нужен canonpath. Если я выдам следующее: $str = Win32::GetLongPathName($str); , то, похоже, он изменится на правильный регистр, даже если $ str указывает относительный путь.

2. canonpath это просто получить косые черты в стиле Windows в путях, если это имело значение.

Ответ №2:

Я использую cygwin и svn, и я нашел этот вопрос, когда svn не смог найти эти файлы, потому что он учитывал регистр

например, $ cd /cygdrive /c / svn / delphi2010 /lib / контрольная сумма # неверный регистр

$ svn ls svn: предупреждение: W155010: узел ‘/cygdrive/c/svn / delphi2010 /lib / контрольная сумма’ не найден. svn: E200009: не удалось перечислить все цели, потому что некоторые цели не существуют

$ eval cd $( cygpath $( perl -le ‘использовать Win32; $ d= cygpath -aw . ; chomp($d); распечатать Win32::GetLongPathName($ d)’ ) )

$ pwd /cygdrive/c /svn/ Delphi2010/lib / Контрольная сумма # обратите внимание, что регистр восстановлен

и svn ls снова работает!