如何从 Python 中的路径中获取没有扩展名的文件名?

2024-12-11 08:47:00
admin
原创
166
摘要:问题描述:如何从 Python 中的路径中获取没有扩展名的文件名?"/path/to/some/file.txt" → "file" 解决方案 1:Python 3.4+使用pathlib.Path.stem>>> from pathlib imp...

问题描述:

如何从 Python 中的路径中获取没有扩展名的文件名?

"/path/to/some/file.txt"  →  "file"

解决方案 1:

Python 3.4+

使用pathlib.Path.stem

>>> from pathlib import Path
>>> Path("/path/to/file.txt").stem
'file'
>>> Path("/path/to/file.tar.gz").stem
'file.tar'

Python < 3.4

os.path.splitext与以下结合使用os.path.basename

>>> os.path.splitext(os.path.basename("/path/to/file.txt"))[0]
'file'
>>> os.path.splitext(os.path.basename("/path/to/file.tar.gz"))[0]
'file.tar'

解决方案 2:

在 Python 3.4+ 中使用.stemfrompathlib

from pathlib import Path

Path('/root/dir/sub/file.ext').stem

将会回归

'file'

请注意,如果您的文件有多个扩展名,.stem则只会删除最后一个扩展名。例如,Path('file.tar.gz').stem将返回'file.tar'

解决方案 3:

你可以用以下方法制作自己的:

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

请参阅下文解决该问题的其他答案。

解决方案 4:

>>> print(os.path.splitext(os.path.basename("/path/to/file/hemanth.txt"))[0])
hemanth

解决方案 5:

在 Python 3.4+ 中,你可以使用pathlib解决方案

from pathlib import Path

print(Path(your_path).resolve().stem)

解决方案 6:

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'

解决方案 7:

正如 @IceAdor 在对 @user2902201 的解决方案的评论中所指出的,rsplit这是对多个周期具有鲁棒性的最简单的解决方案(通过将拆分数限制为maxsplit仅 1(从字符串末尾开始))。

具体如下:

file = 'my.report.txt'
print file.rsplit('.', maxsplit=1)[0]

我的报告

解决方案 8:

如果你想保留文件路径并删除扩展名

>>> file = '/root/dir/sub.exten/file.data.1.2.dat'
>>> print ('.').join(file.split('.')[:-1])
/root/dir/sub.exten/file.data.1.2

解决方案 9:

如果扩展中有多个点,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

解决方案 10:

使用 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

解决方案 11:

import os
filename, file_extension =os.path.splitext(os.path.basename('/d1/d2/example.cs'))
  • 文件名为“示例”

  • 文件扩展名是 '.cs'

解决方案 12:

但即使我导入 os,我也无法将其称为 path.basename。是否可以像 basename 一样直接调用它?

import os,然后使用os.path.basename

importingos并不意味着你可以os.foo不参考就使用os

解决方案 13:

我想我会对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'

解决方案 14:

其他方法不会删除多个扩展名。有些方法还会对没有扩展名的文件名产生问题。此代码片段处理这两个实例,并且适用于 Python 2 和 Python 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

解决方案 15:

一个多扩展感知程序。适用于strunicode路径。适用于 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'

解决方案 16:

import os
path = "a/b/c/abc.txt"
print os.path.splitext(os.path.basename(path))[0]

解决方案 17:

import os

filename = C:\\Users\\Public\\Videos\\Sample Videos\\wildlife.wmv

这将返回filename不包含extension(C:\Users\Public\Videos\Sample Videos\wildlife)的文件

temp = os.path.splitext(filename)[0]  

现在你可以filename从临时文件中获取

os.path.basename(temp)   #this returns just the filename (wildlife)

解决方案 18:

非常非常非常简单,没有其他模块!!!

import os
p = r"C:UsersilalDocumentsace Recognition pythonimgs
orthon.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)

解决方案 19:

使用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]:

更新

这个答案不知为何被否决了。

无论如何,我刚刚找到了一个更好的解决方案。

我第一次发布答案时并不知道有这个str.rsplit功能。使用它我不需要做两次反转。

表现:

In [11]: file = 'D:/ffmpeg/ffmpeg.exe'

In [12]: file.split('/')[-1][::-1].split('.', 1)[1][::-1]
Out[12]: 'ffmpeg'

In [13]: file.split('/')[-1].rsplit('.', 1)[0]
Out[13]: 'ffmpeg'

In [14]: %timeit file.split('/')[-1].rsplit('.', 1)[0]
359 ns ± 4.59 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

In [15]: %timeit file.split('/')[-1][::-1].split('.', 1)[1][::-1]
556 ns ± 3.9 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

解决方案 20:

在 Windows 系统上,我也使用了驱动程序名称前缀,例如:

>>> s = 'c:\\temp\\akarmi.txt'
>>> print(os.path.splitext(s)[0])
c:    empakarmi

因此,由于我不需要驱动器号或目录名,因此我使用:

>>> print(os.path.splitext(os.path.basename(s))[0])
akarmi

解决方案 21:

改进@spinup 的回答:

fn = pth.name
for s in pth.suffixes:
    fn = fn.rsplit(s)[0]
    break
    
print(fn)      # thefile 

这也适用于没有扩展名的文件名

解决方案 22:

我读过答案,发现有很多好的解决方案。因此,对于那些想要获得(名称或扩展名)的人来说,这里有另一个解决方案,使用os 模块,这两种方法都支持具有多个扩展名的文件。

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 上不支持带有“\”字符的文件名

解决方案 23:

假设您已经在使用pathlibPython 3.9 或更新版本,这里有一个简单的单行方法可以删除所有扩展。

>>> from pathlib import Path
>>> pth = Path("/path/to.some/file.foo.bar.txt")
>>> pth.name.removesuffix("".join(pth.suffixes))
'file'

解决方案 24:

我们可以做一些简单的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

解决方案 25:

为了方便起见,一个简单的函数包装了两个方法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 测试。

解决方案 26:

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

解决方案 27:

解决这个问题最简单的方法是

import ntpath 
print('Base name is ',ntpath.basename('/path/to/the/file/'))

这可以节省您的时间和计算成本。

解决方案 28:

我并没有仔细观察,但我没有看到任何人使用正则表达式来解决这个问题。

我将这个问题解释为“给定一条路径,返回不带扩展名的基本名称”。

例如

"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

解决方案 29:

pathlib.Path使用字符串操作来拆分路径的所有扩展的快速函数:

def split_extensions(path: str | Path) -> tuple[str, str]:
    ext = "".join(Path(path).suffixes)
    return str(path).rstrip(ext), ext

# Usage
# >>> split_extensions("./data.tar") => ("./data", ".tar")
# >>> split_extensions("./data.tar.gz") => ("./data", ".tar.gz")

编辑:

感谢@nick-k9的提醒:

rstrip() 接受“指定要删除的字符集的字符串。您需要使用 removesuffix()

removesuffix()从 Python >= 3.9 开始可用

def split_extensions(path: str | Path) -> tuple[str, str]:
    ext = "".join(Path(path).suffixes)
    return str(path).removesuffix(ext), ext

# Usage
# >>> split_extensions("./data.tar") => ("./data", ".tar")
# >>> split_extensions("./data.tar.gz") => ("./data", ".tar.gz")

解决方案 30:

特别推荐你使用 pathlib

from pathlib import Path

path = Path("/path/to/some/file.txt")
filename_without_extension = path.stem
print(filename_without_extension) 

所以你得到了回报

# Output: file
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用