簡體   English   中英

如何從 Python 中的路徑獲取不帶擴展名的文件名?

[英]How do I get the filename without the extension from a path in Python?

如何從 Python 中的路徑獲取不帶擴展名的文件名?

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

獲取不帶擴展名的文件名:

import os
print(os.path.splitext("/path/to/some/file.txt")[0])

印刷:

/path/to/some/file

os.path.splitext的文檔

重要提示:如果文件名有多個點,則僅刪除最后一個后的擴展名。 例如:

import os
print(os.path.splitext("/path/to/some/file.txt.zip.asc")[0])

印刷:

/path/to/some/file.txt.zip

如果您需要處理這種情況,請參閱下面的其他答案。

在 Python .stem中使用來自pathlib的 .stem

from pathlib import Path

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

將返回

'file'

請注意,如果您的文件有多個擴展名, .stem只會刪除最后一個擴展名。 例如, Path('file.tar.gz').stem將返回'file.tar'

您可以自己制作:

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

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

from pathlib import Path

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

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

如果您想保留文件的路徑並刪除擴展名

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

正如@IceAdor 在對@user2902201 解決方案的評論中所指出的那樣, rsplit是對多個周期具有魯棒性的最簡單的解決方案(通過將拆分數量限制為maxsplit僅 1(從字符串的末尾開始))。

這里是這樣寫的:

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

我的報告

以為我會在不需要使用數組索引的情況下對os.path.splitext的使用進行更改。

function 始終返回(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的情況下使用os.foo

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

幾個場景下使用 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'

import os

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

這將返回不帶extension名的filename名 (C:\Users\Public\Videos\Sample Videos\wildlife)

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 系統上,我也使用了驅動程序名稱前綴,例如:

>>> 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 模塊,這兩種方法都支持具有多個擴展名的文件。

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

為方便起見,一個簡單的 function 包裝了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

下面的呢?

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

使用pathlib.Path.stem是 go 的正確方法,但這是一個丑陋的解決方案,它比基於 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]:

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

這里/path/to/file/varun.txt是文件的路徑,output 是varun

# 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 並且適用於復合文件類型和普通文件類型

為了獲得最大的秘密,為了一個有趣的 oneliner,並了解一些關於 itertools 的知識:

def strip_suffix(filename):
    """
    >>> video.mp4
    video

    >>> video.extra.mp4
    video.extra
    """
    return ''.join((name_dot[0] + name_dot[1] for name_dot in itertools.zip_longest(filename.split('.')[0:-1], '.', fillvalue='.')))[0:-1]

注意:這只是為了好玩。 不要使用這個。 改用os.path.splitext

我認為最簡單的方法是使用.split("/")

input= "PATH/TO/FILE/file.txt" file_only = input.split("/")[-1] print(file_only)

>>> file.txt

您也可以這樣做來提取最后一個文件夾:

input= "PATH/TO/FOLDER" folder_only = input.split("/")[-1] print(folder_only)

>>> FOLDER

如果您想要倒數第二個文件夾,只需將 [-1] 更改為 [-2]。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM