ChatGPT解决这个技术问题 Extra ChatGPT

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

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

"/path/to/some/file.txt"  →  "file"
在找到现代 Python 的明确正确答案之前,我不得不滚动很远: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] 简单
@walid 仅当您假设文件名不包含点时 os.path.basename("/path/to/some/file.foo.bar.txt").split('.')[0] 将返回不正确的结果,而 pathlib 将正确处理它
@JosVerlinde 是的,你是对的,但这可以用这个 '.'.join(os.path.basename("/path/to/some/file.foo.bar.txt").split('.')[:-1]) 来解决,它看起来更好看也更容易使用 pathlib 但有时不值得为一个简单的任务加载整个包
偏好和看法不同。我更喜欢简单的代码,需要更少的错误和更新。

O
Ord

获取不带扩展名的文件名:

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

如果您需要处理这种情况,请参阅下面的其他答案。


如果这是一个足够普遍的操作,也许它应该值得它自己的官方命令?类似 os.path.filename(path_to_file) 而不是 os.path.splitext(os.path.basename(path_to_file))[0]
如果文件名包含多个点怎么办?
对于任何想知道与 matteok 相同的人,如果有多个点,splitext 在最后一个拆分(所以 splitext('kitty.jpg.zip') 给出 ('kitty.jpg', '.zip'))。
请注意,此代码返回完整的文件路径(不带扩展名),而不仅仅是文件名。
是的,所以你必须做 splitext(basename('/some/path/to/file.txt'))[0] (我总是似乎在做)
B
Boris Verkhovskiy

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


这是自 python 3 以来推荐的方式。
请注意,与 os.path 解决方案一样,这只会删除一个扩展名(或 suffix,如 pathlib 所称)。 Path('a.b.c').stem == 'a.b'
@hoan 我认为反复调用 .with_suffix('') 是要走的路。您可能希望循环到 p.suffix == ''
它不适用于具有复杂扩展名的文件:pathlib.Path('backup.tar.gz').stem -> 'backup.tar 但预期为 backup
@pymen 这取决于您定义为“扩展”的内容。 Fantastic Mr.Fox.mp4 怎么样?
A
Alan W. Smith

您可以自己制作:

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

有关解决该问题的其他答案,请参见下文。


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

为此+1。 3个完全相同的答案,但这是最直接的答案。您可以使用 ` 来显示代码,并使用“/somepath/hermanth.txt”作为路径实例。
@hemanth.hm 请注意,在您提供的此声明中,os.path.basename 不是必需的。 os.path.basename 应该只用于从文件路径中获取文件名。
B
Boris Verkhovskiy

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

from pathlib import Path

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

为什么要resolve()路径?真的有可能获得文件的路径并且没有文件名是路径的一部分吗?这意味着如果您提供符号链接的路径,您将返回符号链接指向的文件的文件名(不带扩展名)。
使用 resolve() 的一个可能原因是帮助处理多点问题。如果路径是'./foo.tar.gz',下面关于使用索引的答案将不起作用
j
jjisnow

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'

对于从完整路径中删除扩展的一般情况,这是最好的 python 3 解决方案。使用 stem 也会删除父路径。如果您期望双重扩展名(例如 bla.tar.gz),那么您甚至可以使用它两次:p.with_suffix('').with_suffix('')。
D
Dheeraj Chakravarthi

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

index_of_dot = file_name.index('.') 这将在获取文件的基本名称后完成,以便它不会在 .env 处拆分
重要的是,像这样的一系列扩展很常见。 .tar.gz .tar.bz .tar.7z
请注意,如果在 haystack 中找不到针(在上述情况下为点 .),'haystack'.index('needle') 将引发 ValueError 异常。也存在没有任何扩展名的文件。
要解决该问题,请使用 try-catch,或使用 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

如果要在最后一个期间拆分,请使用 rsplit: '/root/dir/sub.exten/file.data.1.2.dat'.rsplit('.', 1)
m
mirekphd

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

这里是这样写的:

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

我的报告


S
ScottMcC

以为我会在不需要使用数组索引的情况下对 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.splittext() 是版本 3.6+
D
Devin Jeanpierre

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

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

import使用 os 并不意味着您可以使用 os.foo 而无需参考 os


但如果您想直接调用 foo,您可以使用 from os import foo
如果 os 模块有一个名为 foo 的成员,那么您就有了一个非常非标准的 os 模块版本。
这是一个占位符名称。 (例如考虑 pathwalk)。
M
MEdwin
import os
filename, file_extension =os.path.splitext(os.path.basename('/d1/d2/example.cs'))

文件名是“示例”

文件扩展名是'.cs'

'


这实际上回答了OP的问题
A
Alan W. Smith

其他方法不会删除多个扩展名。有些还存在没有扩展名的文件名问题。这个片段处理这两个实例,并且在 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)
这不适用于文件名 nvdcve-1.1-2002.json.zip
我在 fileBasename.split('.json')[0] 上拆分它并且它有效
S
SpinUp

几个场景下使用 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

佚名

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

o
oak

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)

B
Bilal

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

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)

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

Z
Zéiksz

在 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

M
M Ganesh

改进@spinup 答案:

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

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


e
esteban21

我已经阅读了答案,我注意到有很多好的解决方案。因此,对于那些想要获得(名称或扩展名)的人来说,这里有另一个解决方案,使用 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 上的此解决方案不支持带有“\”字符的文件名


C
Community

我们可以做一些简单的 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.splitext()[0] 做同样的事情。
如果扩展中有多个点,@CharlesPlager os.path.splitext() 将不起作用。 stackoverflow.com/a/37760212/1250044
它对我有用: In [72]: os.path.splitext('one.two.three.ext') Out[72]: ('one.two.three', '.ext')
h
handle

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


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

N
Nkoro Joseph Ahamefula

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

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

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


J
John Carrell

我看起来不是很努力,但我没有看到有人使用正则表达式来解决这个问题。

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

例如

"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]:

w
wolfrevo

下面的呢?

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

J
John---
# 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 并且适用于复合文件类型和普通文件类型


您的答案可以通过额外的支持信息得到改进。请edit添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。您可以找到有关如何写出好答案的更多信息in the help center
我需要从 "/path/to/some/file.txt" 获取字符串中的 /path/to/some/。我怎样才能做到这一点?