Python+glob从项目根目录获取指定文件(脚本在子目录)
解决方案
方法1:使用pathlib(推荐)
pathlib是Python3.4+内置的面向对象路径操作库,比glob/os模块更直观,能彻底规避工作目录变化带来的路径问题。
from pathlib import Path # 获取脚本的绝对目录(不受运行环境工作目录影响) script_dir = Path(__file__).resolve().parent # 从脚本目录向上两级,定位到repo根目录 repo_root = script_dir.parent.parent # 递归匹配所有以"some-naming-convention-folder"开头的文件夹下的txt文件 txt_files = list(repo_root.glob("some-naming-convention-folder*/**/*.txt")) # 额外排除自身所在的folder1目录(可选,因为上面的glob已限定目标文件夹) txt_files = [f for f in txt_files if "folder1" not in f.parts]
方法2:使用os.walk()
如果习惯传统os模块写法,可通过遍历目录筛选目标文件:
import os # 定位repo根目录 script_path = os.path.abspath(__file__) script_dir = os.path.dirname(script_path) repo_root = os.path.dirname(os.path.dirname(script_dir)) txt_files = [] for root, _, files in os.walk(repo_root): # 检查当前路径是否包含目标命名格式的文件夹 if any(d.startswith("some-naming-convention-folder") for d in root.split(os.sep)): # 收集所有txt文件 txt_files.extend(os.path.join(root, f) for f in files if f.endswith(".txt")) # 排除folder1相关文件 txt_files = [f for f in txt_files if "folder1" not in os.path.normpath(f).split(os.sep)]
方法3:修正glob写法
之前glob失败的核心原因是依赖了不确定的当前工作目录,先定位绝对根目录再拼接glob模式即可解决:
import glob import os # 定位repo根目录 script_dir = os.path.dirname(os.path.abspath(__file__)) repo_root = os.path.dirname(os.path.dirname(script_dir)) # 用绝对路径拼接glob规则 all_my_files = glob.glob(os.path.join(repo_root, "some-naming-convention-folder*/**/*.txt"), recursive=True) # 排除folder1目录的文件 all_my_files = [f for f in all_my_files if "folder1" not in os.path.normpath(f).split(os.sep)]
为什么之前的写法失效?
/just-my-repo-name/**/file.txt:这是系统根目录开头的绝对路径,但Jenkins的工作目录通常不是系统根目录,路径不存在。../**/file.txt:相对路径的基准是Jenkins的任务工作目录,而非脚本所在目录,导致../指向的不是repo根目录。./just-my-repo-name/*.txt:同样基于当前工作目录,而脚本本身就在repo内部,该路径不存在。
核心原则:永远通过__file__推导绝对路径,不要依赖当前工作目录写相对路径,这样本地和Jenkins环境下的路径逻辑完全一致。
内容的提问来源于stack exchange,提问作者ApJo
相关产品推荐
相关产品推荐

