如何让Python 2.7的glob.glob适配可选子目录?
在Python 2.7中用标准glob.glob实现可选子目录的文件搜索
没问题,咱们可以通过构造两种匹配模式并合并结果的方式解决这个问题——毕竟Python 2.7的标准glob.glob不支持**这种递归通配符(你之前的代码里用**能在有Project_1时生效,大概率是因为环境里装了glob2,但既然要求用标准库,就得换个思路)。
核心思路
你的需求是匹配两种路径结构:
- 包含
Project_1子目录的路径 - 不包含
Project_1子目录的路径
我们可以分别为这两种结构写glob匹配模式,然后把结果合并去重即可。
解决方案代码
import glob # 定义两种匹配模式,若Project_1是固定名称,可把Project_*改成Project_1 pattern_with_project = "/starting_path/Data/Intensities/BaseCalls/Primary_Analysis_Results/results/FASTQ_*/Project_*/trimming_*/*_stats.txt" pattern_without_project = "/starting_path/Data/Intensities/BaseCalls/Primary_Analysis_Results/results/FASTQ_*/trimming_*/*_stats.txt" # 获取两种模式的搜索结果 paths_with_project = glob.glob(pattern_with_project) paths_without_project = glob.glob(pattern_without_project) # 合并结果并去重(避免极端情况下重复匹配) stats_paths = list(set(paths_with_project + paths_without_project)) # 若需要保持原始顺序,可改用这种方式去重(速度稍慢但保留顺序) # stats_paths = paths_with_project + [path for path in paths_without_project if path not in paths_with_project]
进阶方案:用os.walk精确筛选
如果你的目录结构可能有更多变化,或者需要更严格的路径校验,直接用os.walk遍历筛选会更灵活:
import os stats_paths = [] # 起始目录 root_dir = "/starting_path/Data/Intensities/BaseCalls/Primary_Analysis_Results/results" for dirpath, _, filenames in os.walk(root_dir): for filename in filenames: if filename.endswith("_stats.txt"): # 把当前目录相对于根目录的路径拆分成部分 rel_parts = os.path.relpath(dirpath, root_dir).split(os.sep) # 校验两种合法的路径结构 # 结构1: FASTQ_*/Project_1/trimming_* if len(rel_parts) == 3: if rel_parts[0].startswith("FASTQ_") and rel_parts[1] == "Project_1" and rel_parts[2].startswith("trimming_"): stats_paths.append(os.path.join(dirpath, filename)) # 结构2: FASTQ_*/trimming_* elif len(rel_parts) == 2: if rel_parts[0].startswith("FASTQ_") and rel_parts[1].startswith("trimming_"): stats_paths.append(os.path.join(dirpath, filename))
为什么你原来的代码不行?
Python 2.7的标准glob模块不支持**这种递归通配符,它只会把**当作普通字符串处理。你之前的模式FASTQ_*/**/trimming_*/*_stats.txt其实强制要求在FASTQ_*和trimming_*之间至少存在一层目录,所以当没有Project_1时,FASTQ_*下面直接是trimming_*,就匹配不到了。
内容的提问来源于stack exchange,提问作者Luc
相关产品推荐
相关产品推荐

