Как удалить неверные символы пути в Python?

Каков наиболее кросс-платформенный способ удаления символов неправильного пути (например, «\» или «:» в Windows) в Python?

Решение

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

def remove(value, deletechars):
    for c in deletechars:
        value = value.replace(c,'')
    return value;

print remove(filename, '\/:*?"<>|')

person Martin    schedule 23.06.2009    source источник
comment
может немного быстрее, если путь длинный: .join(i for i in value if i not in r'\/:*?‹›|')   -  person fortran    schedule 24.09.2009
comment
@fortran, это должен быть ответ, а не комментарий - по моему личному мнению, это очень «питоново». Спасибо.   -  person kcpr    schedule 04.11.2016
comment
Но как насчет символа :, указывающего диск, например. C:\Downloads? Нам нужно сохранить это, не так ли?   -  person Jason    schedule 24.06.2018


Ответы (4)


К сожалению, набор допустимых символов зависит от ОС и от файловой системы.

  • Windows:

    • Use almost any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:
      • The following reserved characters are not allowed:
        < > : " / \ | ? *
      • Не допускаются символы, чьи целочисленные представления находятся в диапазоне от нуля до 31.
      • Любой другой символ, который не разрешен целевой файловой системой.

    Список допустимых символов может варьироваться в зависимости от операционной системы и региона компьютера, на котором файловая система была впервые отформатирована.

    .NET имеет GetInvalidFileNameChars и GetInvalidPathChars, но я не знаю, как вызывать их из Питон.

  • Mac OS: NUL is always excluded, "/" is excluded from POSIX layer, ":" excluded from Apple APIs
    • HFS+: any sequence of non-excluded characters that is representable by UTF-16 in the Unicode 2.0 spec
    • HFS: любая последовательность неисключенных символов, представленная в MacRoman (по умолчанию) или других кодировках, в зависимости от машины, создавшей файловую систему.
    • UFS: то же, что и HFS+
  • Linux:
    • native (UNIX-like) filesystems: any byte sequence excluding NUL and "/"
    • FAT, NTFS, другие неродные файловые системы: различается

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

person ephemient    schedule 23.06.2009
comment
Обратите внимание, что в Windows у вас также будут проблемы, если вы попытаетесь использовать имена файлов, такие как CON.*. И пробелы в конце имени файла тоже могут вызывать проблемы. - person Antimony; 29.03.2013
comment
@Antimony Да, устаревшие имена устройств DOS не могут использоваться в качестве имен файлов в Win32. Но файловая система прекрасно их поддерживает, и использование NT API для обхода Win32 работает нормально. (По крайней мере, насколько я помню, у меня больше нет машины с Windows для тестирования.) - person ephemient; 30.03.2013
comment
Вы можете сделать это с помощью NT API, но Python не может. Python для Windows, к сожалению, ограничен в обработке имен файлов. Хуже всего то, что часто неверные имена файлов будут молча завершаться ошибкой или давать вам файл, отличный от того, который вы просили (попробуйте открыть CON в сценарии, запускаемом из консоли). - person Antimony; 30.03.2013

Я думаю, что самый безопасный подход здесь — просто заменить любые подозрительные символы. Итак, я думаю, вы можете просто заменить (или избавиться) все, что не является буквенно-цифровым, -, _, пробелом или точкой. И вот как вы это делаете:

import re
re.sub('[^\w\-_\. ]', '_', filename)

Вышеупомянутое экранирует каждый символ, который не является буквой, '_', '-', '.' или пробелом с '_'. Так что, если вы смотрите на весь путь, вы также захотите добавить os.sep в список разрешенных символов.

Вот пример вывода:

In [27]: re.sub('[^\w\-_\. ]', '_', 'some\\*-file._n\\\\ame')
Out[27]: 'some__-file._n__ame'
person Josh    schedule 27.11.2012
comment
+1, полезный ответ. Нужно ли экранировать эти обратные косые черты? - person LarsH; 04.02.2013
comment
Лучше использовать необработанную строку. - person pepr; 04.02.2013
comment
Да... Я думаю, что если вы не используете r'...', вам все равно понадобится обратная косая черта перед каждой из этих обратных косых черт. Таким образом, всего 10 обратных слэшей. - person LarsH; 04.02.2013
comment
Похоже, я увлекся последним редактированием. Это было правильно, как это было. Имейте в виду, что разрешены только определенные символы (не исключая набор символов). Необработанная строка была ненужной. См. мое разъяснение и образец вывода в обновленном ответе. - person Josh; 05.02.2013
comment
Если вы хотите объединить несколько экранированных символов в один _, добавьте + в строку поиска регулярного выражения: '[^\w\-_\. ]+' - person Bryan P; 20.03.2021

Если вы используете python, попробуйте os.path, чтобы избежать межплатформенных проблем с путями. .

person Macarse    schedule 23.06.2009
comment
Какая часть os.path помогает определить допустимые имена файлов? .supports_unicode_filenames может немного, но этого недостаточно. - person ephemient; 23.06.2009

Этот символ находится в os.sep, это будет «\» или «:», в зависимости от того, в какой системе вы работаете.

person eduffy    schedule 23.06.2009
comment
Сюда не входят :%/‹›^|?, которые также являются недопустимыми файловыми символами в Windows. - person ephemient; 23.06.2009