在 bash shell 中,请考虑以下内容:
$ x="-name 'foo bar'"
$ find $x
find: paths must precede expression: `bar''
$ find -name 'foo bar'
./foo bar
我可以放入什么$x
来让find $x
行为变得像find -name 'foo bar'
?
答案1
不要将单独的内容 (-name
和foo bar
) 放入单个字符串中。
相反,使用数组:
args=( -name 'foo bar' )
find . "${args[@]}"
数组变量扩展周围的引号确保每个元素都被单独引用。这确保了这foo bar
是一个单一的参数。
您还可以使用位置参数:
set -- -name 'foo bar'
find . "$@"
再次强调,引用"$@"
是必不可少的。
当您放入-name 'foo bar'
变量并使用不带引号的变量时find
,shell 会在空格、制表符和换行符上拆分该值。这意味着该find
实用程序获取参数-name
、'foo
和bar'
。由于bar'
不知道该参数find
,因此它会抱怨。
如果字符串中有通配模式(如 )-name '*.txt'
,那么 shell 会将其拆分为-name
和'*.txt'
,然后用作'*.txt'
通配模式来扩展当前目录中的名称。
答案2
注意:Linux 支持 find 语法,但它并不通用。它不适用于大多数 BSD 衍生品,例如,产生以下结果:
bash-3.2$ find -name 'foo bar'
find: illegal option -- n
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
你的问题不是位置,而是引用和引用解释。您可以将您的代码替换为
x='foo bar'
find -name "$x"
或者,您可以尝试使用 eval:
x="-name 'foo bar'"
eval "find $x"
至少在我的系统上导致:
bash-5.1$ x="-name 'foo bar'"
bash-5.1$ eval "find $x"
./foo bar
我相信这是期望的结果。