Extract file name from path, no matter what the os/path format
无论操作系统或路径格式如何,我都可以使用哪个python库从路径中提取文件名?
例如,我希望所有这些路径返回我
1 2 3 4 5 6 7 | 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 |
实际上,有一个函数可以返回您想要的
1 | print(os.path.basename(your_path)) |
按照其他人的建议,使用
Windows路径可以使用反斜杠或正斜杠作为路径分隔符。因此,
1 2 | import ntpath ntpath.basename("a/b/c") |
当然,如果文件以斜杠结尾,则basename将为空,因此请使用自己的函数来处理它:
1 2 3 | def path_leaf(path): head, tail = ntpath.split(path) return tail or ntpath.basename(head) |
验证:
1 2 3 4 | >>> 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)有一个警告:Linux文件名可能包含反斜杠。因此,在Linux上,
O.P.P.分裂是你要找的功能吗
1 2 3 4 5 6 | head, tail = os.path.split("/tmp/d/a.dat") >>> print(tail) a.dat >>> print(head) /tmp/d |
1 2 3 | import os head, tail = os.path.split(p) print tail |
假设p是输入字符串,tail是您想要的。
详见python os module docs
在Python 3中
1 2 3 | >>> from pathlib import Path >>> Path("/tmp/d/a.dat").name 'a.dat' |
在您的示例中,您还需要从右侧去掉斜线以返回
1 2 3 4 5 | >>> import os >>> path = 'a/b/c/' >>> path = path.rstrip(os.sep) # strip the slash from the right side >>> os.path.basename(path) 'c' |
二级:
1 2 | >>> os.path.filename(os.path.dirname(path)) 'b' |
更新:我认为
1 | fname = str("C:\Windows\paint.exe").split('\')[-1:][0] |
这将返回:paint.exe
change the sep value of the split function regarding your path or OS.
这适用于Linux和Windows以及标准库。
1 2 3 4 5 6 7 | 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] |
结果:
1 | ['c', 'c', 'c', 'c', 'c', 'c', 'c'] |
我从未见过双反斜杠路径,它们存在吗?python模块
1 2 3 4 | 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)) |
如果您的文件路径没有以"/"结尾,并且目录之间用"/"分隔,则使用以下代码。正如我们所知,通常路径不会以"/"结尾。
1 2 3 | import os path_str ="/var/www/index.html" print(os.path.basename(path_str)) |
但在某些情况下,比如URL以"/"结尾,然后使用以下代码
1 2 3 4 | import os path_str ="/home/some_str/last_str/" split_path = path_str.rsplit("/",1) print(os.path.basename(split_path[0])) |
但是,当您的路径由""指定时(通常在Windows路径中找到),则可以使用以下代码
1 2 3 4 5 6 7 8 | import os path_str ="c:\\var\www\index.html" print(os.path.basename(path_str)) import os path_str ="c:\\home\some_str\last_str\" split_path = path_str.rsplit("\",1) print(os.path.basename(split_path[0])) |
您可以通过检查操作系统类型并返回结果,将两者合并为一个函数。
Windows分隔符可以是UNIX文件名或Windows路径。Unix分隔符只能存在于Unix路径中。Unix分隔符的存在表示非Windows路径。
下面将通过操作系统特定的分隔符剥离(切割尾随分隔符),然后拆分并返回最右边的值。它很难看,但基于上述假设,它很简单。如果假设不正确,请更新,我将更新此响应以匹配更准确的条件。
1 | a.rstrip("\\\" if a.count("/") == 0 else '/').split("\\\" if a.count("/") == 0 else '/')[-1] |
样例代码:
1 2 3 4 5 | 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的解决方案,它似乎可以与任何操作系统上的任何操作系统路径一起工作。
不需要其他模块,也不需要预处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 line'] print([extract_basename(path) for path in extra_paths]) # ['C:', 'alone', 'space in filename', 'multi line'] |
可以在这里测试regex。
也许只是我的多功能一体解决方案,没有重要的新功能(关于创建临时文件的tempfile:d)
1 2 3 4 | import tempfile abc = tempfile.NamedTemporaryFile(dir='/tmp/') abc.name abc.name.replace("/","").split()[-1] |
得到EDOCX1[11]的值将是这样一个字符串:EDOCX1[12]所以我可以用一个空格来替换
不需要导入任何模块。
最好的问候
4K3ND0
为了完整起见,下面是针对python 3.2+的
1 2 3 4 5 6 7 | >>> 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上都有效。
在python 2和3中,使用模块pathlib2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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) |
用途:
1 2 3 4 5 6 7 8 | 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'] |
对于您的测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
这里的想法是将所有路径转换为
如果参数
1 | filename = path[path.rfind('/')+1:] |