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

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

当前回答

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

其他回答

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

我们可以做一些简单的拆分/弹出魔术,如图所示(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()将无法工作。

例如,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

您只需找到basename中第一个点的索引,然后对basename进行切片,即可获得不带扩展名的文件名。

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

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

改进@spinup答案:

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

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