如何从 Python 中的路径获取不带扩展名的文件名?
"/path/to/some/file.txt" → "file"
from pathlib import Path; print(Path("/path/to/some/file.txt").stem)
>>> file
os.path
执行相同操作,如下 os.path.basename("/path/to/some/file.txt").split('.')[0]
简单
os.path.basename("/path/to/some/file.foo.bar.txt").split('.')[0]
将返回不正确的结果,而 pathlib 将正确处理它
'.'.join(os.path.basename("/path/to/some/file.foo.bar.txt").split('.')[:-1])
来解决,它看起来更好看也更容易使用 pathlib
但有时不值得为一个简单的任务加载整个包
获取不带扩展名的文件名:
import os
print(os.path.splitext("/path/to/some/file.txt")[0])
印刷:
/path/to/some/file
Documentation for os.path.splitext
。
重要提示:如果文件名有多个点,则仅删除最后一个后的扩展名。例如:
import os
print(os.path.splitext("/path/to/some/file.txt.zip.asc")[0])
印刷:
/path/to/some/file.txt.zip
如果您需要处理这种情况,请参阅下面的其他答案。
在 Python 3.4+ 中使用 pathlib
中的 .stem
from pathlib import Path
Path('/root/dir/sub/file.ext').stem
将返回
'file'
请注意,如果您的文件有多个扩展名,.stem
只会删除最后一个扩展名。例如,Path('file.tar.gz').stem
将返回 'file.tar'
。
os.path
解决方案一样,这只会删除一个扩展名(或 suffix
,如 pathlib
所称)。 Path('a.b.c').stem == 'a.b'
.with_suffix('')
是要走的路。您可能希望循环到 p.suffix == ''
。
pathlib.Path('backup.tar.gz').stem
-> 'backup.tar
但预期为 backup
Fantastic Mr.Fox.mp4
怎么样?
您可以自己制作:
>>> import os
>>> base=os.path.basename('/root/dir/sub/file.ext')
>>> base
'file.ext'
>>> os.path.splitext(base)
('file', '.ext')
>>> os.path.splitext(base)[0]
'file'
重要提示:如果文件名中有多个 .
,则仅删除最后一个。例如:
/root/dir/sub/file.ext.zip -> file.ext
/root/dir/sub/file.ext.tar.gz -> file.ext.tar
有关解决该问题的其他答案,请参见下文。
>>> print(os.path.splitext(os.path.basename("/path/to/file/hemanth.txt"))[0])
hemanth
`
来显示代码,并使用“/somepath/hermanth.txt”作为路径实例。
os.path.basename
不是必需的。 os.path.basename
应该只用于从文件路径中获取文件名。
https://docs.python.org/3/library/os.path.html
在 python 3 pathlib 中,“pathlib 模块提供了高级路径对象。”所以,
>>> from pathlib import Path
>>> p = Path("/a/b/c.txt")
>>> p.with_suffix('')
WindowsPath('/a/b/c')
>>> p.stem
'c'
如果扩展中有多个点,os.path.splitext() 将不起作用。
例如,images.tar.gz
>>> import os
>>> file_path = '/home/dc/images.tar.gz'
>>> file_name = os.path.basename(file_path)
>>> print os.path.splitext(file_name)[0]
images.tar
您可以在基本名称中找到第一个点的索引,然后对基本名称进行切片以仅获取不带扩展名的文件名。
>>> import os
>>> file_path = '/home/dc/images.tar.gz'
>>> file_name = os.path.basename(file_path)
>>> index_of_dot = file_name.index('.')
>>> file_name_without_extension = file_name[:index_of_dot]
>>> print file_name_without_extension
images
.tar.gz
.tar.bz
.tar.7z
.
),'haystack'.index('needle')
将引发 ValueError 异常。也存在没有任何扩展名的文件。
str.find()
并检查 -1。如果没有点,则返回 file_name
如果您想保留文件的路径并删除扩展名
>>> file = '/root/dir/sub.exten/file.data.1.2.dat'
>>> print ('.').join(file.split('.')[:-1])
/root/dir/sub.exten/file.data.1.2
'/root/dir/sub.exten/file.data.1.2.dat'.rsplit('.', 1)
正如@IceAdor 在对@user2902201 解决方案的评论中指出的那样,rsplit
是最简单的解决方案,对多个周期具有鲁棒性(通过将拆分数量限制为仅 1 的 maxsplit
(从字符串末尾开始))。
这里是这样写的:
file = 'my.report.txt'
print file.rsplit('.', maxsplit=1)[0]
我的报告
以为我会在不需要使用数组索引的情况下对 os.path.splitext 的使用进行变体。
该函数始终返回一个 (root, ext)
对,因此可以安全使用:
root, ext = os.path.splitext(path)
例子:
>>> import os
>>> path = 'my_text_file.txt'
>>> root, ext = os.path.splitext(path)
>>> root
'my_text_file'
>>> ext
'.txt'
但即使我导入 os,我也无法将其命名为 path.basename。是否可以像 basename 一样直接调用它?
import os
,然后使用 os.path.basename
import
使用 os
并不意味着您可以使用 os.foo
而无需参考 os
。
from os import foo
。
os
模块有一个名为 foo
的成员,那么您就有了一个非常非标准的 os
模块版本。
path
或 walk
)。
import os
filename, file_extension =os.path.splitext(os.path.basename('/d1/d2/example.cs'))
文件名是“示例”
文件扩展名是'.cs'
'
其他方法不会删除多个扩展名。有些还存在没有扩展名的文件名问题。这个片段处理这两个实例,并且在 Python 2 和 3 中都有效。它从路径中获取基本名称,将值拆分为点,然后返回第一个,它是文件名的初始部分。
import os
def get_filename_without_extension(file_path):
file_basename = os.path.basename(file_path)
filename_without_extension = file_basename.split('.')[0]
return filename_without_extension
这是一组要运行的示例:
example_paths = [
"FileName",
"./FileName",
"../../FileName",
"FileName.txt",
"./FileName.txt.zip.asc",
"/path/to/some/FileName",
"/path/to/some/FileName.txt",
"/path/to/some/FileName.txt.zip.asc"
]
for example_path in example_paths:
print(get_filename_without_extension(example_path))
在每种情况下,打印的值都是:
FileName
Path('/path/to/file.txt').stem
快得多。 (1,23μs 与 8.39μs)
几个场景下使用 Pathlib 的答案
使用 Pathlib,当只有一个扩展名(或没有)时获取文件名是微不足道的,但处理多个扩展名的一般情况可能会很尴尬。
零或一扩展
from pathlib import Path
pth = Path('./thefile.tar')
fn = pth.stem
print(fn) # thefile
# Explanation:
# the `stem` attribute returns only the base filename, stripping
# any leading path if present, and strips the extension after
# the last `.`, if present.
# Further tests
eg_paths = ['thefile',
'thefile.tar',
'./thefile',
'./thefile.tar',
'../../thefile.tar',
'.././thefile.tar',
'rel/pa.th/to/thefile',
'/abs/path/to/thefile.tar']
for p in eg_paths:
print(Path(p).stem) # prints thefile every time
两个或更少的分机
from pathlib import Path
pth = Path('./thefile.tar.gz')
fn = pth.with_suffix('').stem
print(fn) # thefile
# Explanation:
# Using the `.with_suffix('')` trick returns a Path object after
# stripping one extension, and then we can simply use `.stem`.
# Further tests
eg_paths += ['./thefile.tar.gz',
'/abs/pa.th/to/thefile.tar.gz']
for p in eg_paths:
print(Path(p).with_suffix('').stem) # prints thefile every time
任意数量的扩展(0、1 或更多)
from pathlib import Path
pth = Path('./thefile.tar.gz.bz.7zip')
fn = pth.name
if len(pth.suffixes) > 0:
s = pth.suffixes[0]
fn = fn.rsplit(s)[0]
# or, equivalently
fn = pth.name
for s in pth.suffixes:
fn = fn.rsplit(s)[0]
break
# or simply run the full loop
fn = pth.name
for _ in pth.suffixes:
fn = fn.rsplit('.')[0]
# In any case:
print(fn) # thefile
# Explanation
#
# pth.name -> 'thefile.tar.gz.bz.7zip'
# pth.suffixes -> ['.tar', '.gz', '.bz', '.7zip']
#
# If there may be more than two extensions, we can test for
# that case with an if statement, or simply attempt the loop
# and break after rsplitting on the first extension instance.
# Alternatively, we may even run the full loop and strip one
# extension with every pass.
# Further tests
eg_paths += ['./thefile.tar.gz.bz.7zip',
'/abs/pa.th/to/thefile.tar.gz.bz.7zip']
for p in eg_paths:
pth = Path(p)
fn = pth.name
for s in pth.suffixes:
fn = fn.rsplit(s)[0]
break
print(fn) # prints thefile every time
已知第一个扩展名的特殊情况
例如,如果扩展名可以是 .tar
、.tar.gz
、.tar.gz.bz
等;您可以简单地 rsplit
已知扩展名并获取第一个元素:
pth = Path('foo/bar/baz.baz/thefile.tar.gz')
fn = pth.name.rsplit('.tar')[0]
print(fn) # thefile
一个多扩展感知过程。适用于 str
和 unicode
路径。在 Python 2 和 3 中工作。
import os
def file_base_name(file_name):
if '.' in file_name:
separator_index = file_name.index('.')
base_name = file_name[:separator_index]
return base_name
else:
return file_name
def path_base_name(path):
file_name = os.path.basename(path)
return file_base_name(file_name)
行为:
>>> path_base_name('file')
'file'
>>> path_base_name(u'file')
u'file'
>>> path_base_name('file.txt')
'file'
>>> path_base_name(u'file.txt')
u'file'
>>> path_base_name('file.tar.gz')
'file'
>>> path_base_name('file.a.b.c.d.e.f.g')
'file'
>>> path_base_name('relative/path/file.ext')
'file'
>>> path_base_name('/absolute/path/file.ext')
'file'
>>> path_base_name('Relative\\Windows\\Path\\file.txt')
'file'
>>> path_base_name('C:\\Absolute\\Windows\\Path\\file.txt')
'file'
>>> path_base_name('/path with spaces/file.ext')
'file'
>>> path_base_name('C:\\Windows Path With Spaces\\file.txt')
'file'
>>> path_base_name('some/path/file name with spaces.tar.gz.zip.rar.7z')
'file name with spaces'
import os
filename = C:\\Users\\Public\\Videos\\Sample Videos\\wildlife.wmv
这将返回没有 extension
(C:\Users\Public\Videos\Sample Videos\wildlife) 的 filename
temp = os.path.splitext(filename)[0]
现在您可以从 temp 中获取 filename
os.path.basename(temp) #this returns just the filename (wildlife)
非常非常非常简单,没有其他模块!!!
import os
p = r"C:\Users\bilal\Documents\face Recognition python\imgs\northon.jpg"
# Get the filename only from the initial file path.
filename = os.path.basename(p)
# Use splitext() to get filename and extension separately.
(file, ext) = os.path.splitext(filename)
# Print outcome.
print("Filename without extension =", file)
print("Extension =", ext)
import os
path = "a/b/c/abc.txt"
print os.path.splitext(os.path.basename(path))[0]
在 Windows 系统上,我也使用了 drivername 前缀,例如:
>>> s = 'c:\\temp\\akarmi.txt'
>>> print(os.path.splitext(s)[0])
c:\temp\akarmi
所以因为我不需要驱动器号或目录名,所以我使用:
>>> print(os.path.splitext(os.path.basename(s))[0])
akarmi
改进@spinup 答案:
fn = pth.name
for s in pth.suffixes:
fn = fn.rsplit(s)[0]
break
print(fn) # thefile
这也适用于没有扩展名的文件名
我已经阅读了答案,我注意到有很多好的解决方案。因此,对于那些想要获得(名称或扩展名)的人来说,这里有另一个解决方案,使用 os module,这两种方法都支持具有多个扩展名的文件。
import os
def get_file_name(path):
if not os.path.isdir(path):
return os.path.splitext(os.path.basename(path))[0].split(".")[0]
def get_file_extension(path):
extensions = []
copy_path = path
while True:
copy_path, result = os.path.splitext(copy_path)
if result != '':
extensions.append(result)
else:
break
extensions.reverse()
return "".join(extensions)
注意:Windows 上的此解决方案不支持带有“\”字符的文件名
我们可以做一些简单的 split
/ pop
魔术,如此处所示 (https://stackoverflow.com/a/424006/1250044),以提取文件名(尊重 windows 和 POSIX 差异)。
def getFileNameWithoutExtension(path):
return path.split('\\').pop().split('/').pop().rsplit('.', 1)[0]
getFileNameWithoutExtension('/path/to/file-0.0.1.ext')
# => file-0.0.1
getFileNameWithoutExtension('\\path\\to\\file-0.0.1.ext')
# => file-0.0.1
为方便起见,一个简单的函数包装了 os.path
中的两个方法:
def filename(path):
"""Return file name without extension from path.
See https://docs.python.org/3/library/os.path.html
"""
import os.path
b = os.path.split(path)[1] # path, *filename*
f = os.path.splitext(b)[0] # *file*, ext
#print(path, b, f)
return f
使用 Python 3.5 测试。
import os
list = []
def getFileName( path ):
for file in os.listdir(path):
#print file
try:
base=os.path.basename(file)
splitbase=os.path.splitext(base)
ext = os.path.splitext(base)[1]
if(ext):
list.append(base)
else:
newpath = path+"/"+file
#print path
getFileName(newpath)
except:
pass
return list
getFileName("/home/weexcel-java3/Desktop/backup")
print list
解决这个问题的最简单方法是
import ntpath
print('Base name is ',ntpath.basename('/path/to/the/file/'))
这可以节省您的时间和计算成本。
我看起来不是很努力,但我没有看到有人使用正则表达式来解决这个问题。
我将问题解释为“给定路径,返回不带扩展名的基本名称”。
例如
"path/to/file.json"
=> "file"
"path/to/my.file.json"
=> "my.file"
在 Python 2.7 中,我们仍然没有 pathlib
...
def get_file_name_prefix(file_path):
basename = os.path.basename(file_path)
file_name_prefix_match = re.compile(r"^(?P<file_name_pre fix>.*)\..*$").match(basename)
if file_name_prefix_match is None:
return file_name
else:
return file_name_prefix_match.group("file_name_prefix")
get_file_name_prefix("path/to/file.json")
>> file
get_file_name_prefix("path/to/my.file.json")
>> my.file
get_file_name_prefix("path/to/no_extension")
>> no_extension
使用 pathlib.Path.stem
是正确的方法,但这是一个丑陋的解决方案,它比基于 pathlib 的方法更有效。
您有一个文件路径,其字段由正斜杠 /
分隔,斜杠不能出现在文件名中,因此您将文件路径拆分为 /
,最后一个字段是文件名。
扩展名始终是通过点 .
拆分文件名创建的列表的最后一个元素,因此如果您反转文件名并按点拆分一次,则第二个元素的反向是不带扩展名的文件名。
name = path.split('/')[-1][::-1].split('.', 1)[1][::-1]
表现:
Python 3.9.10 (tags/v3.9.10:f2f3f53, Jan 17 2022, 15:14:21) [MSC v.1929 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.28.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from pathlib import Path
In [2]: file = 'D:/ffmpeg/ffmpeg.exe'
In [3]: Path(file).stem
Out[3]: 'ffmpeg'
In [4]: file.split('/')[-1][::-1].split('.', 1)[1][::-1]
Out[4]: 'ffmpeg'
In [5]: %timeit Path(file).stem
6.15 µs ± 433 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [6]: %timeit file.split('/')[-1][::-1].split('.', 1)[1][::-1]
671 ns ± 37.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [7]:
下面的呢?
import pathlib
filename = '/path/to/dir/stem.ext.tar.gz'
pathlib.Path(filename).name[:-len(''.join(pathlib.Path(filename).suffixes))]
# -> 'stem'
还是这个等价物?
pathlib.Path(filename).name[:-sum(map(len, pathlib.Path(filename).suffixes))]
# use pathlib. the below works with compound filetypes and normal ones
source_file = 'spaces.tar.gz.zip.rar.7z'
source_path = pathlib.Path(source_file)
source_path.name.replace(''.join(source_path.suffixes), '')
>>> 'spaces'
尽管上面描述了许多工作实现,但我添加了这个 ^,因为它仅使用 pathlib 并且适用于复合文件类型和普通文件类型
"/path/to/some/file.txt"
获取字符串中的 /path/to/some/
。我怎样才能做到这一点?
不定期副业成功案例分享
splitext('kitty.jpg.zip')
给出('kitty.jpg', '.zip')
)。splitext(basename('/some/path/to/file.txt'))[0]
(我总是似乎在做)