在POSIX Shell脚本中能否将多个命令参数存入变量并在后续命令中展开?
在POSIX Shell脚本中能否将多个命令参数存入变量并在后续命令中展开?
当然可以,但这里有个容易踩坑的细节要注意:如果你的参数都是单字、不含空格或特殊字符,直接用普通变量存了再展开完全没问题,但如果参数里包含空格、引号或者通配符,普通变量的展开方式会把这些特殊字符当成参数分隔符,导致命令执行出错。
先看你给出的示例场景
你代码里的mode变量就是单字参数的情况,不管是+111还是/111,直接在find命令里用$mode展开完全正常:
rootname="$1" case "$(uname)" in Darwin) mode='+111' ;; Linux) mode='/111' ;; esac # 这里直接展开mode没问题 find "$rootname" -perm "$mode"
但如果要存多个带特殊字符的参数怎么办?
POSIX标准的shell没有数组(像bash/zsh里的数组是扩展特性),所以咱们得用位置参数配合set命令来实现,这是POSIX兼容的通用方法:
比如你想给find添加多个参数,包括可能带空格的文件名或者复杂选项,可以这么写:
rootname="$1" # 先清空位置参数列表 set -- # 逐个添加需要的参数 set -- "$@" -type f # 根据系统添加权限参数 case "$(uname)" in Darwin) set -- "$@" -perm +111 ;; Linux) set -- "$@" -perm /111 ;; esac # 如果rootname不为空,添加路径参数 if [ -n "$rootname" ]; then set -- "$@" "$rootname" fi # 用"$@"展开所有参数,每个参数都会被正确识别 find "$@"
这里的核心是"$@"——它会把每个位置参数作为单独的项展开,不管参数里有没有空格、引号,都不会被错误拆分。
为什么普通变量不行?
举个反例:如果你尝试用普通变量存多个参数:
args="-type f -perm +111 '/path with spaces'" find $args
执行时shell会把'/path with spaces'拆成三个参数:'/path、with、spaces',完全不是你想要的效果。而用set和"$@"就能完美避免这个问题。
备注:内容来源于stack exchange,提问作者PRouleau
相关产品推荐
相关产品推荐

