Bash递归函数make_request遍历单分支后提前终止问题排查
问题根因
递归函数仅遍历单路径就提前终止的核心原因有两个:
- 最核心的问题是变量未做局部作用域隔离:bash中默认变量都是全局生效的,你在for循环里用的计数变量
c、读取的count/child/fileType/path全是全局变量。递归进入子目录调用make_request时,内层函数的for循环会直接篡改外层函数的c变量值。当第一个最深分支遍历完成返回上层时,c的值已经被内层循环累加到大于等于外层循环的count阈值,外层for循环直接判定结束,根本不会执行同级第二个及之后的目录分支。 - 第二处错误是curl命令外层多余的
$()命令替换包裹:这种写法会尝试将curl的标准输出作为shell命令执行,虽然你加了&> /dev/null暂时没触发命令执行错误,但属于无意义的危险写法,极端场景下会导致脚本异常退出。
修复方案
- 在函数开头用
local关键字声明所有函数内使用的变量,隔离不同递归层级的作用域,避免内层递归篡改外层的循环计数 - 去掉curl命令外层无意义的
$()包裹,直接执行curl命令 - 所有变量引用统一加双引号包裹,避免路径含空格、特殊字符时出现解析异常
修复后完整代码
make_request(){ # 声明局部变量,隔离递归层级作用域 local path count c child fileType path="${1//' '/'%20'}" echo "$path" mkdir -p "$HOME/$1" # 去掉外层无意义的$(),直接执行curl curl --output "$HOME/$1/$FILE_NAME" -v -X GET "$BASE_URL/$API_METHOD/$path" &> /dev/null count=$(jq ".count" "$HOME/$1/$FILE_NAME") for (( c=0; c<count; c++ )) do child=$(jq -r ".items[$c].path" "$HOME/$1/$FILE_NAME"); fileType=$(jq -r ".items[$c].type" "$HOME/$1/$FILE_NAME"); if [ "$fileType" == "folder" ]; then make_request "$child" fi done } make_request "/"
修复后每个递归层级的计数变量、业务变量都是独立的,内层循环修改值不会影响外层循环的执行流程,即可完整遍历所有目录分支。
内容的提问来源于stack exchange,提问作者gg-dev-05
相关产品推荐
相关产品推荐

