Неоднозначный разделитель пути в Windows — как с этим справиться?

Еще один вопрос вызвал интересную проблему:

В Windows Java File.pathSeparatorChar равно ;, что правильно. Однако на самом деле точка с запятой также является допустимым символом для имен папок или файлов. Вы можете создать папку с именем Test;Test1 в Windows.

Возникает вопрос: как определить, действительно ли точка с запятой в списке путей разделяет путь или является частью имени каталога, если список путей может содержать как абсолютные, так и относительные пути?


person Thorsten Dittmar    schedule 14.04.2015    source источник


Ответы (3)


Если путь содержит сам ;, путь должен быть заключен в двойные кавычки ".

после небольшого PoC

mkdir "foo;bar"
echo echo execute %%~dpnx0 > "foo;bar\dummy.cmd"
set PATH=%PATH%;"foo;bar"
dummy.cmd

вывод будет

execute R:\temp\foo;bar\dummy.cmd

означает, что dummy.cmd найден с помощью настройки пути.

edit Как видно из комментариев: использование точки с запятой может привести к некоторым проблемам. Лучше избегать использования имен каталогов, содержащих точку с запятой.

person SubOptimal    schedule 14.04.2015
comment
Ага! Сейчас мы говорим. Это кажется разумным. - person Thorsten Dittmar; 14.04.2015
comment
Интересно, это работает, но когда я попробовал which dummy, он этого не нашел. - person Always Learning; 14.04.2015
comment
Вы имеете в виду where dummy? - person Thorsten Dittmar; 14.04.2015
comment
@stvcisco Если вы имеете в виду инструменты Unix which, это должно быть which dummy.cmd. Но это не найдено. Так как where dummy.cmd тоже не нашел файл, то which винить в этом не буду. ;-) - person SubOptimal; 14.04.2015
comment
@ThorstenDittmar Спасибо за команду where (до сих пор этого не знал). Исходя из того, что это тоже не в состоянии справиться с этим делом. Кажется, либо ; не должно быть разрешено, либо обработка каталогов каким-то образом нарушена. - person SubOptimal; 14.04.2015
comment
Хотя это, кажется, работает и является (предположительно) правильным способом анализа такого PATH, я настоятельно рекомендую не добавлять имена каталогов, содержащие точки с запятой, в PATH в производственных системах. - person Harry Johnston; 15.04.2015
comment
@HarryJohnston Я полностью с тобой согласен. Я добавляю примечание к своему ответу, чтобы никто не мог видеть, что его раньше не предупреждали. ;-) - person SubOptimal; 15.04.2015

Поскольку вопрос касается Java и основан на ответе @SubOptimal, который объясняет, что пути с точкой с запятой должны быть заключены в кавычки, вот небольшой пример кода для извлечения путей из такого списка, разделенного File.pathSeparator:

String separatedList  = "\"test;test1\";c:\\windows;\"test2\";test3;;test4";

String pattern = String.format("(?:(?:\"([^\"]*)\")|([^%1$s]+))%1$s?", File.pathSeparator);
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(separatedList);
while (m.find())
{
    for (int i = 1; i <= m.groupCount(); i++)
    {
        String path = m.group(i);
        if (path != null)
            System.out.println(path);
    }
}

Для справки, регулярное выражение без экранирующих символов — (?:(?:"([^"]*)")|([^;]+));?.

person Métoule    schedule 14.04.2015

В Windows PATH точка с запятой всегда является разделителем. Если у вас есть папка с точкой с запятой в имени, вы можете поместить ее короткое альтернативное имя в поле PATH. Чтобы найти короткое имя, используйте DIR /X. Например:

C:\> dir test* /X
<DIR>   **TEST_T~1**     Test;Test1
C:\> set PATH=TEST_T~1;%PATH%
person Always Learning    schedule 14.04.2015
comment
Хотя я мог бы это сделать, это действительно противоречит цели разрешения длинных имен путей, не так ли? - person Thorsten Dittmar; 14.04.2015
comment
Проблема не в длине имени, а в том, что оно содержит разделитель пути. Если вы хотите, чтобы PATH интерпретировал вашу папку как папку, вам нужно использовать форму, которая не содержит разделителя. - person Always Learning; 14.04.2015