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

当前回答

也许只是我的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]的元素

不需要导入任何模块。

其他回答

os.path.split 这是你要找的函数吗

head, tail = os.path.split("/tmp/d/a.dat")

>>> print(tail)
a.dat
>>> print(head)
/tmp/d
import os
head, tail = os.path.split('path/to/file.exe')

尾巴是你想要的,文件名。

详见python os模块文档

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

这是一个仅适用于regex的解决方案,它似乎适用于任何OS上的任何OS路径。

不需要其他模块,也不需要预处理:

import re

def extract_basename(path):
  """Extracts basename of a given path. Should Work with any OS Path on any OS"""
  basename = re.search(r'[^\\/]+(?=[\\/]?$)', path)
  if basename:
    return basename.group(0)


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

print([extract_basename(path) for path in paths])
# ['c', 'c', 'c', 'c', 'c', 'c', 'c']


extra_paths = ['C:\\', 'alone', '/a/space in filename', 'C:\\multi\nline']

print([extract_basename(path) for path in extra_paths])
# ['C:', 'alone', 'space in filename', 'multi\nline']

更新:

If you only want a potential filename, if present (i.e., /a/b/ is a dir and so is c:\windows\), change the regex to: r'[^\\/]+(?![\\/])$' . For the "regex challenged," this changes the positive forward lookahead for some sort of slash to a negative forward lookahead, causing pathnames that end with said slash to return nothing instead of the last sub-directory in the pathname. Of course there is no guarantee that the potential filename actually refers to a file and for that os.path.is_dir() or os.path.is_file() would need to be employed.

这将匹配如下:

/a/b/c/             # nothing, pathname ends with the dir 'c'
c:\windows\         # nothing, pathname ends with the dir 'windows'
c:hello.txt         # matches potential filename 'hello.txt'
~it_s_me/.bashrc    # matches potential filename '.bashrc'
c:\windows\system32 # matches potential filename 'system32', except
                    # that is obviously a dir. os.path.is_dir()
                    # should be used to tell us for sure

正则表达式可以在这里测试。

像其他人建议的那样使用os.path.split或os.path.basename并不能在所有情况下工作:如果您在Linux上运行脚本并试图处理经典的windows样式的路径,它将失败。

Windows路径可以使用反斜杠或正斜杠作为路径分隔符。因此,ntpath模块(相当于os. path)在windows上运行时的路径)将适用于所有平台上的所有(1)路径。

import ntpath
ntpath.basename("a/b/c")

当然,如果文件以斜杠结束,basename将为空,所以创建自己的函数来处理它:

def path_leaf(path):
    head, tail = ntpath.split(path)
    return tail or ntpath.basename(head)

验证:

>>> 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']
>>> [path_leaf(path) for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']

(1) There's one caveat: Linux filenames may contain backslashes. So on linux, r'a/b\c' always refers to the file b\c in the a folder, while on Windows, it always refers to the c file in the b subfolder of the a folder. So when both forward and backward slashes are used in a path, you need to know the associated platform to be able to interpret it correctly. In practice it's usually safe to assume it's a windows path since backslashes are seldom used in Linux filenames, but keep this in mind when you code so you don't create accidental security holes.