Shell递归目录函数传参异常:$1与$2参数递归时接收值错误
问题核心原因
你的参数传递逻辑存在本质错误:
递归调用行perform_fragmented_copy "$1"/* $n_curr_depth中,"$1"/*是shell通配符展开项,会把目标目录下所有子文件/子目录的路径拆成独立参数依次传入,你要传递的深度值$n_curr_depth会被挤到所有展开路径的后面,根本不会落到$2的位置。
举个对应你报错场景的例子:当$1为/home/ROSS-82/,目录下存在82、ross_reader-82两个子项时,这行调用实际展开等价于:
perform_fragmented_copy "/home/ROSS-82//82" "/home/ROSS-82//ross_reader-82" 1
此时函数接到的参数里,$1是第一个子路径/home/ROSS-82//82,$2是第二个子路径/home/ROSS-82//ross_reader-82,你预期的深度值1被排到了$3的位置,自然会触发「integer expression expected」的报错,和你输出的错误现象完全吻合。
除此之外你用while [ "$1" ] + shift的遍历逻辑也有问题:当递归层传入多个路径参数时,shift会依次把参数左移,最后会把排在末尾的深度值也当成路径处理,进一步打乱参数逻辑。
修复方案
调整参数顺序:把深度值固定作为函数的第一个入参,后面所有位置都放待处理的路径。这样无论传入多少个路径,深度值的位置永远不会被展开的通配符挤掉,遍历路径时从第二个参数开始取即可。
修复后的完整代码:
perform_fragmented_copy() { # 第一个参数固定为当前遍历深度,取出后直接shift,剩余参数全是待处理路径 local n_curr_depth=$1 shift # 超过最大深度直接终止当前层递归 if (( n_curr_depth > n_max_depth )); then return fi local entry n_entry_size # 遍历当前层所有传入的路径 for entry in "$@"; do echo "perform_fragmented_copy: $entry at depth $n_curr_depth" n_entry_size=$(du -sb "$entry" | awk '{print $1}') if (( sz_remainig_destination > n_entry_size )); then echo "perform_fragmented_copy: can do the copy" # 此处补充实际复制逻辑 else echo "perform_fragmented_copy: cannot, iterating subentries" # 递归调用:先传+1后的深度,再传当前目录下的所有子项 perform_fragmented_copy $((n_curr_depth + 1)) "$entry"/* fi done echo "perform_fragmented_copy: exiting depth level $n_curr_depth" }
对应调整函数调用方式,先传初始深度0,再传入起始目录路径:
sz_remainig_destination=10000 n_max_depth=5 perform_fragmented_copy 0 "$1"
编码注意事项
- 所有路径变量引用时必须加双引号,避免路径包含空格、特殊字符时出现解析错误
- 多参数遍历优先用
for 变量 in "$@"实现,比while+shift逻辑更清晰,也不容易出现参数错位问题 - 递归函数内的变量尽量加
local修饰为局部变量,避免不同递归层级的变量互相污染 - 整数判断优先用
(( ))双括号语法,比[ ]中括号的整数比较写法更简洁,容错性更高
内容的提问来源于stack exchange,提问作者Akhil V Suku
相关产品推荐
相关产品推荐

