小坑记录: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() 的默认顺序是 "系统依赖的",手动排序是 "跨平台一致的"------ 这是编写可靠代码的必要步骤。

相关推荐
计算机毕设指导627 分钟前
基于微信小程序+django连锁火锅智慧餐饮管理系统【源码文末联系】
java·后端·python·mysql·微信小程序·小程序·django
小鸡脚来咯43 分钟前
RabbitMQ详解(从入门到实战)
开发语言·后端·ruby
古城小栈1 小时前
Spring Boot 3.3 整合 AI 工具链:自动生成接口文档
人工智能·spring boot·后端
踏浪无痕1 小时前
为什么 Spring Cloud Gateway 必须用 WebFlux?
后端·面试·架构
码匠君1 小时前
Dante Cloud 升级 Spring Boot 4 经验分享
经验分享·spring boot·后端
秋邱1 小时前
Java面向对象进阶:封装、继承、多态的实现逻辑与实战案例
java·开发语言·后端·spring cloud·ar·restful
架构精进之路2 小时前
一文搞懂什么是 Vibe Coding?
人工智能·后端
IT 行者2 小时前
Spring Boot 4 升级指南:告别RestTemplate,拥抱现代HTTP客户端
spring boot·后端·http
qq_12498707532 小时前
基于微信小程序的校园资讯共享平台的设计与实现(源码+论文+部署+安装)
spring boot·后端·微信小程序·小程序·毕业设计
此剑之势丶愈斩愈烈2 小时前
Spring获取URL信息
java·后端·spring