我可以使用哪个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

当前回答

在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的通用解码器,它可以在任何路径上工作。如果这不起作用,您可以使用fromwinpath=True强制识别windows路径。这将把输入字符串分成几个部分,最后一个是你要找的叶子,因此是path2unix(t)[-1]。

如果参数nojoin=False,则路径将被连接回来,因此输出只是转换为Unix格式的输入字符串,这对于跨平台比较子路径非常有用。

其他回答

这是适用于linux和windows以及标准库

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']

def path_leaf(path):
    return path.strip('/').strip('\\').split('/')[-1].split('\\')[-1]

[path_leaf(path) for path in paths]

结果:

['c', 'c', 'c', 'c', 'c', 'c', 'c']

也许只是我的all in one解决方案,没有重要的一些新的(考虑tempfile创建临时文件:D)

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

获取abc.name的值将是这样的字符串:'/tmp/tmpks5oksk7' 所以我可以用空格.replace("/", " ")替换/,然后调用split()。它会返回一个列表,我得到 列表中最后一个带有[-1]的元素

不需要导入任何模块。

为了完整起见,这里是python 3.2+的pathlib解决方案:

>>> 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上都适用。

带扩展名的文件名

filepath = './dir/subdir/filename.ext'
basename = os.path.basename(filepath)
print(basename)
# filename.ext

print(type(basename))
# <class 'str'>

不带扩展名的文件名

basename_without_ext = os.path.splitext(os.path.basename(filepath))[0]
print(basename_without_ext)
# filename

如果你想自动获取文件名,你可以这样做

import glob

for f in glob.glob('/your/path/*'):
    print(os.path.split(f)[-1])