我在一个文件夹中有一堆按数字排序的文件,当我尝试对 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)
一般答案是使用
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
仅从完整文件路径中获取文件名部分(不带后缀)。试试这个:
import glob
import os
files = sorted(glob.glob(f'{os.getcwd()}/*.txt'), key=len)
print(files)
给你:
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)
您似乎正在分割完整路径,而不是基本名称。你可以试试这个:
files = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=lambda x: int(os.path.basename(x).split(' ')[0]))