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

Jenkins Pipeline使用findFiles获取子目录内容的问题求解

Jenkins Pipeline中findFiles枚举子目录文件异常解决方案

问题背景

当前Jenkins环境已安装pipeline-utility-steps插件,findFiles步骤在普通构建任务中可正常调用,但在Pipeline中枚举子目录文件时连续遇到异常,已尝试的写法及对应问题如下:

  • 通配符递归写法
    执行代码:
    def files = findFiles(glob: "dirname/**")
    
    异常表现:进程持续挂起,无返回结果。
  • 切换工作目录写法
    执行代码:
    dir("dirname") {
        def files = findFiles()
    }
    
    异常表现:执行失败,步骤会尝试创建dirname@tmp目录,要求持有父目录写权限;放宽父目录权限后可正常运行,但出于安全要求,不能授予Jenkins服务账号该父目录的写权限。
  • 脚本控制台测试
    在Jenkins脚本控制台执行如下测试代码:
    def files = findFiles() 
    println(files)
    
    抛出异常:
    groovy.lang.MissingMethodException: No signature of method: Script1.findFiles() is applicable for argument types: () values: [] Possible solutions: findAll(), findAll(groovy.lang.Closure), find() 
    

异常原因说明

  1. 脚本控制台调用报错属于预期行为:findFiles是Pipeline专属步骤,不属于Jenkins Groovy沙箱内置方法,无法在Pipeline上下文外的脚本控制台直接调用,该报错不代表插件安装异常。
  2. dir()块权限报错为步骤固有逻辑:dir()步骤切换到非当前工作空间下的目录时,默认会在目标目录同级创建目录名@tmp临时工作目录,该行为无配置项可关闭,因此只要对父目录无写权限,该写法必然失败。
  3. 通配符**写法挂起通常是递归死循环导致:无深度限制的**递归会遍历所有子节点,若目标目录下存在指向上层目录的软链接、挂载的超大容量存储目录,会触发无限递归或遍历超时,最终表现为进程挂起。

可用实现方案

方案1:限定通配符遍历深度,规避死循环

如果不需要无限制深度递归,可明确指定遍历层级,避免触发软链接死循环,该写法全程仅需目标目录读权限,不会创建临时文件:

// 遍历dirname下最多2层子目录的所有文件,可按需增减*/*层级调整深度
def files = findFiles(glob: "dirname/{*,*/*}")
// 遍历3层的写法为 glob: "dirname/{*,*/*,*/*/*}"

方案2:调用原生文件API,绕开dir步骤逻辑

如果需要全量递归遍历,又不能授予父目录写权限,可直接使用Groovy原生文件API操作,完全不依赖dir()步骤,无临时目录创建逻辑:

// 拼接目标目录绝对路径,不需要切换工作目录
def targetPath = "${pwd()}/dirname"
def targetDir = new File(targetPath)
// 递归列出目录下所有文件,内置软链接死循环规避逻辑
def listFiles(File dir) {
  def result = []
  dir.eachFile { file ->
    if (file.isFile()) {
      result << file.absolutePath
    } else if (file.isDirectory() && !file.canonicalPath.startsWith(dir.canonicalPath)) {
      // 跳过指向目录外的软链接,避免死循环
      return
    } else if (file.isDirectory()) {
      result.addAll(listFiles(file))
    }
  }
  return result
}
def files = listFiles(targetDir)

该方案仅要求Jenkins服务账号对目标dirname目录持有读权限,无额外权限要求。

方案3:全量递归时排除异常目录

如果必须使用findFiles的**全量递归逻辑,可通过excludes参数明确排除会导致死循环的软链接目录、大容量挂载目录:

def files = findFiles(
  glob: "dirname/**",
  excludes: "dirname/上层软链接名/**,dirname/大容量挂载目录名/**"
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:09:18