You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python实现文件路径列表中同序列文件的分组处理?

你的当前方案用路径长度来分组显然行不通——按字符串长度分组完全没考虑序列的实际结构和文件夹上下文。我们换个思路,聚焦两个关键信息:文件夹路径(用来区分不同目录下的内容)和序列基础名称(文件名中帧号之前的部分,用来识别属于同一序列的文件)。

核心思路

  1. 对每个路径,拆分出文件夹路径、文件名和扩展名;
  2. 用正则表达式识别文件名中的帧号(影视行业常见命名是帧号在文件名末尾,前缀是下划线或点,比如_1025或.1025);
  3. 以「文件夹路径 + 序列基础名称」作为分组键,这样同一文件夹下的同一序列文件会被归为一组;
  4. 先按分组键排序(因为itertools.groupby只会把连续的相同键分到一组),再按帧号排序,保证分组后的序列是有序的。

完整实现代码

import os
import re
import itertools
import pprint

lpaths = [
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot012/render/SC11_1_Shot012.v01_1025.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot012/render/SC11_1_Shot012.v01_1042.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot012/render/SC11_1_Shot012.v01_1016.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot012/2d/app/Shot012_v1.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot012/2d/app/Shot012_v02.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot004/3d/app2/workspace.cfg',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot004/3d/app2/scenes/SC11_1_Shot004_v01.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot004/3d/app2/scenes/Shot004_camera_v01.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot004/render/SC11_1_Shot004.v01_1112.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot004/render/SC11_1_Shot004.v01_1034.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot004/render/SC11_1_Shot004.v02_1116.exr',
 '/projects/0100/dbu/shots/11_1/SC11_1_Shot004/render/SC11_1_Shot004.v02_1126.exr'
]

def get_sequence_info(path):
    # 获取文件夹路径
    folder = os.path.dirname(path)
    # 获取文件名(含扩展名)
    filename = os.path.basename(path)
    # 拆分文件名和扩展名
    name_without_ext, ext = os.path.splitext(filename)
    
    # 匹配文件名末尾的帧号:前面是_或.,后面是一串数字
    frame_match = re.search(r'([._])(\d+)$', name_without_ext)
    if frame_match:
        # 提取序列基础名称(去掉帧号部分)
        sequence_base = name_without_ext[:frame_match.start()]
        # 提取帧号并转为整数,方便排序
        frame_number = int(frame_match.group(2))
    else:
        # 没有帧号的文件,自身作为一个单帧序列
        sequence_base = name_without_ext
        frame_number = 0
    
    # 分组键:文件夹路径 + 序列基础名称,确保同文件夹同序列的文件被分到一组
    group_key = (folder, sequence_base)
    return group_key, frame_number, path

# 1. 为每个路径生成分组键、帧号和原路径
path_info = [get_sequence_info(p) for p in lpaths]

# 2. 先按分组键排序,再按帧号排序——groupby要求相同键的元素连续排列
sorted_path_info = sorted(path_info, key=lambda x: (x[0], x[1]))

# 3. 按分组键进行分组
sequence_groups = {}
for key, group in itertools.groupby(sorted_path_info, key=lambda x: x[0]):
    # 提取每组中的路径,已经按帧号排好序
    sequence_paths = [item[2] for item in group]
    sequence_groups[key] = sequence_paths

# 打印分组结果
pprint.pprint(sequence_groups)

代码说明

  • get_sequence_info函数:负责解析每个路径的关键信息,识别帧号并生成分组键;
  • 排序步骤:必须先按分组键排序,否则itertools.groupby会把同一序列的分散文件分成多个组;
  • 正则表达式:r'([._])(\d+)$'匹配文件名末尾的数字帧号,如果你有特殊的命名规则(比如帧号在中间、分隔符不同),可以调整这个正则来适配。

输出结果示例

运行后,你会得到一个字典,每个键是(文件夹路径, 序列基础名称),对应的值是该序列的所有路径(按帧号有序):

  • 比如('/projects/0100/dbu/shots/11_1/SC11_1_Shot012/render', 'SC11_1_Shot012.v01')对应的列表是三个按帧号排序的EXR文件;
  • 单文件(比如Shot012_v1.exr)会单独作为一个长度为1的序列组。

内容的提问来源于stack exchange,提问作者Desmond

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:30:20