Извлечение имени файла из пути, независимо от того, какой формат os / path - PullRequest
596 голосов
/ 05 декабря 2011

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

Например, я хотел бы, чтобы все эти пути возвращали мне c:

a/b/c/
a/b/c
\a\b\c
\a\b\c\
a\b\c
a/b/../../a/b/c/
a/b/../../a/b/c

Ответы [ 15 ]

5 голосов
/ 20 марта 2015

Я никогда не видел пути с двойной обратной косой чертой, они существуют? Встроенная функция модуля Python os не работает. Все остальные работают, также предостережение, данное вами с os.path.normpath():

paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...     'a/b/../../a/b/c/', 'a/b/../../a/b/c', 'a/./b/c', 'a\b/c']
for path in paths:
    os.path.basename(os.path.normpath(path))
3 голосов
/ 16 мая 2016

Разделителем Windows может быть имя файла Unix или путь к Windows. Разделитель Unix может существовать только в пути Unix. Наличие разделителя Unix указывает путь не из Windows.

Следующая команда зачистит (разделит конечный разделитель) специальным разделителем ОС, затем разделит и вернет самое правое значение. Это некрасиво, но просто основано на предположении выше. Если предположение неверно, пожалуйста, обновите, и я обновлю этот ответ, чтобы соответствовать более точным условиям.

a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]

пример кода:

b = ['a/b/c/','a/b/c','\\a\\b\\c','\\a\\b\\c\\','a\\b\\c','a/b/../../a/b/c/','a/b/../../a/b/c']

for a in b:

    print (a, a.rstrip("\\" if a.count("/") == 0 else '/').split("\\" if a.count("/") == 0 else '/')[-1])
2 голосов
/ 21 августа 2014

Может быть, просто все в одном решении, без каких-либо новых важных (смотрите временный файл для создания временных файлов: D)

import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1] 

Получение значений abc.name будет такой строкой: '/tmp/tmpks5oksk7' Поэтому я могу заменить / пробелом .replace("/", " "), а затем вызвать split(). Это вернет список, и я получу последний элемент списка с [-1]

Нет необходимости импортировать какой-либо модуль.

С наилучшими пожеланиями

4k3nd0

1 голос
/ 24 августа 2017

Для полноты картины, вот решение pathlib для python 3.2 +:

>>> from pathlib import PureWindowsPath

>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...          'a/b/../../a/b/c/', 'a/b/../../a/b/c']

>>> [PureWindowsPath(path).name for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']

Это работает как в Windows, так и в Linux.

0 голосов
/ 29 декабря 2018

В Python 2 и 3 с использованием модуля pathlib2 :

import posixpath  # to generate unix paths
from pathlib2 import PurePath, PureWindowsPath, PurePosixPath

def path2unix(path, nojoin=True, fromwinpath=False):
    """From a path given in any format, converts to posix path format
    fromwinpath=True forces the input path to be recognized as a Windows path (useful on Unix machines to unit test Windows paths)"""
    if not path:
        return path
    if fromwinpath:
        pathparts = list(PureWindowsPath(path).parts)
    else:
        pathparts = list(PurePath(path).parts)
    if nojoin:
        return pathparts
    else:
        return posixpath.join(*pathparts)

Использование:

In [9]: path2unix('lala/lolo/haha.dat')
Out[9]: ['lala', 'lolo', 'haha.dat']

In [10]: path2unix(r'C:\lala/lolo/haha.dat')
Out[10]: ['C:\\', 'lala', 'lolo', 'haha.dat']

In [11]: path2unix(r'C:\lala/lolo/haha.dat') # works even with malformatted cases mixing both Windows and Linux path separators
Out[11]: ['C:\\', 'lala', 'lolo', 'haha.dat']

С вашим тестовым набором:

In [12]: testcase = paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
    ...: ...     'a/b/../../a/b/c/', 'a/b/../../a/b/c']

In [14]: for t in testcase:
    ...:     print(path2unix(t)[-1])
    ...:
    ...:
c
c
c
c
c
c
c

Идея состоит в том, чтобы преобразовать все пути в единое внутреннее представление pathlib2 с различными декодерами в зависимости от платформы.К счастью, pathlib2 включает в себя универсальный декодер PurePath, который должен работать на любом пути.Если это не работает, вы можете принудительно распознать путь Windows, используя fromwinpath=True.Это разделит входную строку на части, последним будет искомый лист, следовательно, path2unix(t)[-1].

Если аргумент nojoin=False, путь будет соединен обратно, так что выходэто просто входная строка, преобразованная в формат Unix, которая может быть полезна для сравнения подпутей на разных платформах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...