bash递归在单级后自动结束

  • 本文关键字:结束 单级 递归 bash bash
  • 更新时间 :
  • 英文 :


为什么这个make_request函数在一次遍历之后结束?

make_request(){
path="${1//' '/'%20'}"
echo $path
mkdir -p $HOME/"$1"
$(curl --output $HOME/"$1"/$FILE_NAME -v -X GET $BASE_URL"/"$API_METHOD"/"$path &> /dev/null)
# sample response from curl
# {
#     "count":2,
#     "items": [
#         {"path": "somepath1", "type": "folder"},
#         {"path": "somepath2", "type": "folder"},
#     ]
# }
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 "/"

make_request "/"应该给出以下输出:

/folder
/folder/folder1-1
/folder/folder1-1/folder1-2
/folder/foler2-1
/folder/folder2-1/folder2-2
/folder/folder2-1/folder2-3 ...

但是我得到了以下内容:

/folder
/folder/folder1-1
/folder/folder1-1/folder1-2

您到处使用全局变量。因此,内部调用改变了外部调用的循环变量ccount,导致伪造。

最小的例子:

f() {
this_is_global=$1
echo "enter $1: $this_is_global"
((RANDOM%2)) && f "$(($1+1))"
echo "exit $1: $this_is_global"
}

运行f 1打印类似

的内容
enter 1: 1
enter 2: 2
enter 3: 3
exit 3: 3
exit 2: 3
exit 1: 3

解决方案:通过写入local count=$(...)等使变量本地化。对于您的循环,您必须在for之上添加一条额外的语句local c

目前所有变量都有全局作用域;这意味着所有的函数调用都覆盖和引用了相同的变量集,这反过来意味着当子函数返回到父函数时,父函数会发现它的变量已经被子函数覆盖了,这反过来导致了这里看到的行为类型。

在这种特殊情况下,循环变量c离开最后一个子进程,其值为c=$count,所有父循环现在都看到c=$count,因此退出;它实际上变得更有趣,因为count也随着每个函数调用而变化。前面在第一个函数调用之前添加set -x(也就是启用调试模式)的注释应该显示每个函数调用时每个变量的情况。

OP想要做的是确保每个函数都使用变量的local副本。最简单的方法是在函数的顶部添加一个local <variable_list>,确保列出所有应被视为"本地"的变量,例如:

local path count c child fileType

将变量改为局部作用域,而不是全局作用域。

...
local count; # <------ VARIABLE MADE LOCAL
count=$(jq ".count" $HOME/"$1"/$FILE_NAME)
local c; # <------ VARIABLE MADE LOCAL
for (( c=0; c<$count; c++ ))
do
....
done
...

最新更新