如何从环境变量中正确转义命令参数

如何从环境变量中正确转义命令参数

我正在尝试合并 2 个命令的输出find并将其通过管道传递给下一个运算符。传递给两个执行的参数find非常相似,所以我想保持干燥

FIND_CMD_ARGS="-type f \( -iname \*.m -o -iname \*.swift \) -print0"
CMD_OUTPUT=`{ find $PROJECT_PATH -not -path '*/Pods/*' $FIND_CMD_ARGS; find . -path '*/Pods/MyProject*/*' $FIND_CMD_ARGS }`

由于某种原因这不起作用,这是我得到的输出

find: illegal option -- n
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
find: -type f \( -iname \*.m -o -iname \*.swift \) -print0: unknown primary or operator

思考args这个问题与环境变量中的转义方式有关,FIND_CMD_ARGS但我无法找出正确的方法。

有任何想法吗?谢谢!

答案1

如果您希望一个变量存储多个参数,请使用数组:

find_args=(-type f \( -iname \*.m -o -iname \*.swift \) -print)
cmd_output=$(
  find "$PROJECT_PATH" ! -path '*/Pods/*' "${find_args[@]}"
  find . -path '*/Pods/MyProject*/*' "${find_args[@]}"
)

我也

  • 在变量扩展周围添加了缺少的引号
  • 将变量名称更改为小写,因为它看起来不应该是一个环境变量(无论如何,现在它是一个数组,它不能导出到环境中)。
  • 将非标准更改-not为标准!-iname是另一个非标准谓词)。
  • 使用$(...)命令替换的形式代替旧的已弃用的形式`...`
  • 更改-print0为变量-print不能bash存储 NUL 字节。

另一种方法可能是声明一个函数:

myfind() {
  find "$@" -type f \( -iname \*.m -o -iname \*.swift \) -print
}
cmd_output=$(
  myfind "$PROJECT_PATH" ! -path '*/Pods/*'
  myfind . -path '*/Pods/MyProject*/*'
)

现在,您对该变量无能为力,因为您无法可靠地使用.而不是 来$cmd_output获取文件列表。-print-print0

使用 bash 4.4 或更高版本,您可以使用数组代替并使用:

myfind() {
  find "$@" -type f \( -iname \*.m -o -iname \*.swift \) -print0
}
readarray -td '' files < <(
  myfind "$PROJECT_PATH" ! -path '*/Pods/*'
  myfind . -path '*/Pods/MyProject*/*'
)

相关内容