如何对 glob.glob 进行数字排序?

问题描述 投票:0回答:4

我在一个文件夹中有一堆按数字排序的文件,当我尝试对 glob.glob 进行排序时,我从来没有以正确的顺序获得文件。


文件示例和预期输出排序

folder
------
C:\Users\user\Desktop\folder\1 sample.mp3
C:\Users\user\Desktop\folder\2 sample.mp3
C:\Users\user\Desktop\folder\3 sample.mp3
C:\Users\user\Desktop\folder\4 sample.mp3
C:\Users\user\Desktop\folder\5 sample.mp3
... over 800 files...

我尝试过但输出似乎是随机的

files = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=lambda x: (os.path.splitext(os.path.basename(x))[0]))


C:\Users\user\Desktop\folder\1 speech.mp3
C:\Users\user\Desktop\folder\10 speech.mp3 
C:\Users\user\Desktop\folder\100 speech.mp3
C:\Users\user\Desktop\folder\101 speech.mp3
C:\Users\user\Desktop\folder\102 speech.mp3
C:\Users\user\Desktop\folder\103 speech.mp3  
C:\Users\user\Desktop\folder\104 speech.mp3
C:\Users\user\Desktop\folder\105 speech.mp3
C:\Users\user\Desktop\folder\106 speech.mp3
C:\Users\user\Desktop\folder\107 speech.mp3
C:\Users\user\Desktop\folder\108 speech.mp3
C:\Users\user\Desktop\folder\109 speech.mp3
C:\Users\user\Desktop\folder\11 speech.mp3 

尝试按日期或大小排序不是解决方案。

更新 之前的所有答案都效果很好:

l = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=len)
l = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=lambda x: int(os.path.basename(x).split(' ')[0]))

def get_key(fp):
    filename = os.path.splitext(os.path.basename(fp))[0]
    int_part = filename.split()[0]
    return int(int_part)

l = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=get_key)
python list sorting glob
4个回答
6
投票

一般答案是使用

re.match()
捕获数字,并使用
int()
将该数字(字符串)转换为整数。使用这些数字通过
sorted()

对文件进行排序

代码

import re 
import math
from pathlib import Path 

file_pattern = re.compile(r'.*?(\d+).*?')
def get_order(file):
    match = file_pattern.match(Path(file).name)
    if not match:
        return math.inf
    return int(match.groups()[0])

sorted_files = sorted(files, key=get_order)

输入示例

考虑随机文件,其中一个整数数字位于文件名的任何部分

├── 012 some file.mp3
├── 1 file.txt
├── 13 file.mp3
├── 2 another file.txt
├── 3 file.csv
├── 4 file.mp3
├── 6 yet another file.txt
├── 88 name of file.mp3
├── and final 999.txt
├── and some another file7.txt
├── some 5 file.mp3
└── test.py

输出示例

当传递给

get_order()
参数中的
sorted()
内置函数时,
key
可用于对文件进行排序

In [1]: sorted(files, key=get_order)
Out[1]:
['C:\\tmp\\file_sort\\1 file.txt',
 'C:\\tmp\\file_sort\\2 another file.txt',
 'C:\\tmp\\file_sort\\3 file.csv',
 'C:\\tmp\\file_sort\\4 file.mp3',
 'C:\\tmp\\file_sort\\some 5 file.mp3',
 'C:\\tmp\\file_sort\\6 yet another file.txt',
 'C:\\tmp\\file_sort\\and some another file7.txt',
 'C:\\tmp\\file_sort\\012 some file.mp3',
 'C:\\tmp\\file_sort\\13 file.mp3',
 'C:\\tmp\\file_sort\\88 name of file.mp3',
 'C:\\tmp\\file_sort\\and final 999.txt',
 'C:\\tmp\\file_sort\\test.py']

简短说明

  • re.compile
    用于提供小的速度提升(如果多次匹配相同的模式)
  • re.match
    用于匹配正则表达式模式。
  • 在正则表达式模式中,
    .*?
    表示任何字符(
    .
    )、零次或多次(
    *
    )非贪婪(
    ?
    )。
    \d+
    匹配任何数字一次或多次,括号仅捕获与
    groups()
    列表的匹配。
  • 如果不匹配(文件中没有数字),
    match
    将为
    None
    get_order
    给出无穷大;这些文件是任意排序的,但是可以为这些文件添加逻辑(这个问题中没有询问)。
  • sorted()
    函数采用
    key
    参数,该函数应该是可调用的,它采用一个参数:列表中的项目。在这种情况下,它将是这些文件字符串之一(完整文件路径)
  • Path(file).name
    仅从完整文件路径中获取文件名部分(不带后缀)。

6
投票

试试这个:

import glob
import os
files = sorted(glob.glob(f'{os.getcwd()}/*.txt'), key=len)
print(files)

2
投票

给你:

import os, glob

def get_key(fp):
    filename = os.path.splitext(os.path.basename(fp))[0]
    int_part = filename.split()[0]
    return int(int_part)

files = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=get_key)

2
投票

您似乎正在分割完整路径,而不是基本名称。你可以试试这个:

files = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=lambda x: int(os.path.basename(x).split(' ')[0]))
© www.soinside.com 2019 - 2024. All rights reserved.