小坑记录:python中 glob.glob()返回的文件顺序不同

Python 的 glob.glob() 在 Windows 和 Linux 上的核心差异集中在「大小写敏感性、路径分隔符」 (之前已详细说明),而 返回的文件顺序默认是「不确定且不一致」的 ------ 两端的文件顺序大概率不同,这和 os.listdir() 的行为一致,本质是由操作系统的文件系统存储逻辑决定的,而非 glob.glob() 本身的实现差异。

一、核心结论:默认文件顺序「不一致」,且无固定规律

glob.glob() 的返回顺序直接依赖底层文件系统的遍历顺序,而 Windows 和 Linux 的文件系统(NTFS/FAT32 vs ext4)对文件的存储和排序逻辑完全不同,导致两端返回的文件顺序几乎必然不同。

具体原因:

  • Windows(NTFS/FAT32) :文件系统默认按「文件名的 Unicode 编码值(UTF-16)排序」,但早期 FAT32 按「文件创建时的簇顺序」,且大小写不敏感(排序时忽略大小写);
  • Linux(ext4) :文件系统默认按「文件的 inode 编号顺序」排序(inode 是文件的索引节点,分配顺序取决于文件创建时间和磁盘空闲块分布),且大小写敏感(排序时区分大小写)。

示例验证:

假设目录 ./images 下有 3 个文件:a.jpgB.JPGc.jpg

  • Windows 下 glob.glob("./images/*.jpg") 返回顺序(大小写不敏感,按 Unicode 排序):

    plaintext

    css 复制代码
    ['./images\a.jpg', './images\B.JPG', './images\c.jpg']  # 忽略大小写,按 a→B→c 排序(B 的 Unicode 编码小于 c)
  • Linux 下 glob.glob("./images/*.jpg") 返回顺序(大小写敏感,按 inode 顺序):

    plaintext

    css 复制代码
    ['./images/a.jpg', './images/c.jpg', './images/B.JPG']  # 按 inode 分配顺序,B.JPG 因大小写敏感排在最后

    (注:Linux 的 inode 顺序无固定规律,若文件创建顺序是 B.JPGa.jpgc.jpg,返回顺序可能是 B.JPG 在前)。

二、关键补充:同一系统内的顺序也「不保证固定」

即使在同一系统(如 Windows),glob.glob() 的返回顺序也可能变化:

  • 新增 / 删除文件后,文件系统的存储结构变化,遍历顺序可能改变;
  • 不同分区(如 NTFS 分区 vs FAT32 U 盘)的排序逻辑不同,返回顺序也不同。

因此,绝对不能依赖 glob.glob() 的默认顺序编写业务逻辑(如 "取第一个文件作为默认值""按顺序处理文件"),否则跨平台或文件操作后会出现逻辑错误。

三、跨平台兼容方案:手动排序(最佳实践)

若需让 Windows 和 Linux 上返回的文件顺序一致,核心解决方案是:忽略系统默认顺序,手动指定排序规则(如按文件名、创建时间、大小排序)。

方案 1:按文件名排序(最常用,跨平台一致)

手动对 glob.glob() 的结果进行排序,支持「大小写敏感 / 不敏感」两种模式:

python 复制代码
import os
import glob

local_dir_sensor = "./images"
imgtype = "jpg"
pattern = os.path.join(local_dir_sensor, f"*.{imgtype}")

# 1. 基础排序(按文件名字符串排序,依赖系统默认大小写敏感性,不推荐跨平台)
result = sorted(glob.glob(pattern))

# 2. 跨平台兼容排序(忽略大小写,推荐)
result = sorted(glob.glob(pattern), key=lambda x: os.path.basename(x).lower())

示例结果(跨平台一致):

无论 Windows 还是 Linux,排序后均按「文件名小写后的字母顺序」返回:

plaintext 复制代码
# Windows 排序后
['./images\a.jpg', './images\B.JPG', './images\c.jpg']
# Linux 排序后
['./images/a.jpg', './images/B.JPG', './images/c.jpg']

方案 2:按文件创建时间 / 修改时间排序(跨平台一致)

若需按文件的时间顺序处理(如优先处理最新创建的文件),可通过 os.path.getctime()(创建时间)或 os.path.getmtime()(修改时间)排序:

python 复制代码
import os
import glob

pattern = "./images/*.jpg"
# 按文件修改时间排序(最新的在最后)
result = sorted(glob.glob(pattern), key=lambda x: os.path.getmtime(x))
# 按文件创建时间排序(最新的在最前)
result = sorted(glob.glob(pattern), key=lambda x: os.path.getctime(x), reverse=True)

方案 3:按文件大小排序(跨平台一致)

python 复制代码
import os
import glob

pattern = "./images/*.jpg"
# 按文件大小升序排序(从小到大)
result = sorted(glob.glob(pattern), key=lambda x: os.path.getsize(x))

四、glob.glob()pathlib 的顺序差异

若使用 Python 3.4+ 的 pathlib.Path.glob()(更推荐的跨平台路径操作),其默认返回顺序与 glob.glob() 一致(依赖文件系统),但排序方式完全相同 ------ 只需对 Path 对象列表手动排序即可:

python 复制代码
from pathlib import Path

local_dir_sensor = Path("./images")
imgtype = "jpg"
# 获取 Path 对象列表,手动按文件名小写排序
result = sorted(local_dir_sensor.glob(f"*.{imgtype}"), key=lambda p: p.name.lower())
# 转为字符串路径(可选)
result_str = [str(p) for p in result]

五、总结

  1. 默认顺序差异glob.glob() 在 Windows 和 Linux 上的默认返回顺序「不一致」,且无固定规律,依赖文件系统的遍历顺序;
  2. 核心风险:依赖默认顺序会导致跨平台代码逻辑错误,必须避免;
  3. 最佳实践 :无论是否跨平台,都需对 glob.glob() 的结果手动排序(按文件名、时间、大小等),确保顺序可预期;
  4. 跨平台兼容 :排序时使用 os.path.basename(x).lower()(忽略大小写)、os.path.getmtime(x)(时间)等跨平台 API,保证两端排序结果一致。

简单说:glob.glob() 的默认顺序是 "系统依赖的",手动排序是 "跨平台一致的"------ 这是编写可靠代码的必要步骤。

相关推荐
用户2946555091928 分钟前
游戏开发中的向量魔法
后端
兔子零102431 分钟前
nginx 配置长跑(上):从一份 server 到看懂整套路由规则
后端·nginx
啥都学点的程序员34 分钟前
python项目调用shardingsphere时,多进程情况下,shardingsphere配置的连接数会乘以进程数
后端
guchen6634 分钟前
C# 闭包捕获变量的经典问题分析
后端
Lear35 分钟前
Lombok全面解析:极致简化Java开发的神兵利器
后端
小周在成长35 分钟前
Java 单例设计模式(Singleton Pattern)指南
后端
Airene36 分钟前
spring-boot 4 相比 3.5.x 的包依赖变化
spring boot·后端
用户35442543654037 分钟前
别再裸奔了!你的 Spring Boot @Async 正在榨干服务器资源
后端
虎子_layor37 分钟前
小程序登录到底是怎么工作的?一次请求背后的三方信任链
前端·后端