如何让传入bash函数的参数中的$dir变量在for循环内正确展开
Bash exec_all_dirs函数延迟展开$dir变量的实现方案
问题根因
你当前写法无法生效的核心原因是:直接执行"$@"时,Bash会将传入的整段单引号字符串识别为单一命令名查找执行,不会对字符串内部的$dir做变量展开。你需要让Bash在循环内dir变量赋值完成后,再解析执行传入的命令串。
方案1:轻量改动(使用eval,适合个人bashrc场景)
仅需修改exec_all_dirs的执行逻辑,配合调用时用单引号包裹命令即可实现需求:
function exec_all_dirs() { local curdir="$PWD" # 目录数组加双引号兼容带空格的路径 local dirs=( ~/dir1 ~/dir2 ~/dir3 ) for dir in "${dirs[@]}"; do echo "---------- $dir ---------" # 用eval解析执行传入的命令串,此时$dir已赋值会正常展开 eval "$@" done cd "$curdir" } # 调用时保持单引号包裹命令即可,$dir不会提前展开 function all_func() { exec_all_dirs 'cd $dir && another_func_defined_in_bashrc' } function all_du() { exec_all_dirs 'du -sh $dir' }
注意:调用时必须用单引号包裹命令串,如果用双引号会导致$dir在传参阶段就提前展开,不符合预期。
方案2:无eval安全方案(适合复杂场景,避免命令注入风险)
如果担心eval带来的潜在命令注入风险,可以把执行逻辑封装为独立函数,将当前遍历的目录作为参数传入调用,完全规避变量展开时机问题:
function exec_all_dirs() { local curdir="$PWD" local dirs=( ~/dir1 ~/dir2 ~/dir3 ) # 取第一个参数为要执行的动作函数 local action="$1" shift for dir in "${dirs[@]}"; do echo "---------- $dir ---------" # 把当前目录作为第一个参数传给动作函数 "$action" "$dir" "$@" done cd "$curdir" } # 定义all_func对应的动作函数 function _func_action() { local dir="$1" cd "$dir" && another_func_defined_in_bashrc } function all_func() { exec_all_dirs _func_action } # 定义all_du对应的动作函数 function _du_action() { local dir="$1" du -sh "$dir" } function all_du() { exec_all_dirs _du_action }
该方案无需关注变量展开时机,兼容性和安全性更高,适合需要处理带特殊字符的路径、或者命令逻辑复杂的场景。
内容的提问来源于stack exchange,提问作者subtleseeker
相关产品推荐
相关产品推荐

