不知道为什么会产生错误。这是模拟我真实代码的测试代码。我想编写一个包装器find
并希望允许任何参数,因此我将每个参数用单引号括起来。
#!/bin/bash
function find2 {
ARGS="/usr/bin/find"
while [[ $# -gt 0 ]]; do
ARGS="$ARGS '$1'"
shift
done
echo CALLING: $ARGS
$ARGS
}
find2 /tmp/test -name "hello.c" # THIS IS THE DESIRED IMPLEMENTATION (doesn't work)
find '/tmp/test' '-name' 'hello.c' # THIS IS FOR DEBUGGING (works)
我想“find2”工作,但它不起作用。我得到以下输出:
CALLING: /usr/bin/find '/tmp/test' '-name' 'hello.c'
/usr/bin/find: `\'/tmp/test\'': No such file or directory
/usr/bin/find: `\'-name\'': No such file or directory
/usr/bin/find: `\'hello.c\'': No such file or directory
但是,如果我直接使用完全相同的命令(由 find2 生成),它可以正常工作:
/tmp/test/hello.c
不知道发生了什么事。
答案1
(在 Bash 中)您可以更改为值数组:
find2() {
ARGS="/usr/bin/find"
ARGS+=( "$@" )
echo CALLING: "${ARGS[@]}"
"${ARGS[@]}"
}
find2 /tmp/test -name "hello.c"
但这有效并且相当简单:
find2() {
ARGS=( "/usr/bin/find" "$@" )
echo CALLING: "${ARGS[@]}"
"${ARGS[@]}"
}
find2 /tmp/test -name "hello.c"
当然,直接方式也可以(在任何带有函数的 shell 中):
find2() { /usr/bin/find "$@"; }
find2 /tmp/test -name "hello.c"
为什么原来的代码失败了?
要“查看”代码在做什么,您可以使用 set -x 或更好的方法,将 echo 替换为 printf,如下所示:
find2() {
ARGS="/usr/bin/find"
ARGS+=( "$@" )
printf '<%s> ' CALLING: "${ARGS[@]}"; echo
"${ARGS[@]}"
}
find2 /tmp/test -name "hello.c"
当你执行它时,你会看到:
$ ./script.sh
<CALLING:> </usr/bin/find> </tmp/test> <-name> <hello.c>
每个参数都是一个单独的元素(注意 <> 的位置)。
但是,在您的原始代码中(添加 printf):
function find2 {
ARGS="/usr/bin/find"
while [[ $# -gt 0 ]]; do
ARGS="$ARGS '$1'"
shift
done
printf '<%s> ' CALLING: "${ARGS[@]}"; echo
$ARGS
}
find2 /tmp/test -name "hello.c"
执行时你将得到:
$ ./script.sh
<CALLING:> </usr/bin/find '/tmp/test' '-name' 'hello.c'>
所有值都是一个长文本行,而不是单独的参数(请注意 <> 的位置)。
答案2
如果您将该行更改ARGS="$ARGS '$1'"
为ARGS="$ARGS $1"
(删除单引号),它应该可以工作。