查找带有变量参数的命令

查找带有变量参数的命令
> find /etc -name 'shells'
/etc/shells     # good !!

> SEARCH="-name 'shells'"; find /etc $SEARCH
# nothing found - bad !!

为什么“find”命令不能在变量中获取参数?

其他命令在这种模式下工作正常。这可能与空格和解析有关。我如何先在变量中构造参数,然后使用这些参数执行“find”?

要清楚,我想制作 -name xxxx -o -name yyyyy -o -name zzzzz 的链,然后通过一次运行找到所有文件

答案1

您的问题是简单的引号没有被这样解释,而是在您的参数之中。

你认为你已经执行了这个:

find /etc -name 'shells'

但实际上你已经执行了这个:

find /etc -name \'shells\'

记在心上:在 bash 中,双引号内的单引号不会被忽略。

所以解决办法是不放任何简单的引号:

SEARCH="-name shells"; find /etc $SEARCH

更好的解决方案是使用引号,然后使用 eval:

SEARCH="-name 'shells'"; eval " find /etc $SEARCH"

安全问题:永远不要在 eval 参数中使用用户提供的信息。

答案2

我强烈建议避免使用这种方法eval——它在简单的测试中效果很好,但在生产中会出现一些意外的 shell 元字符并造成严重破坏。而且,如果用户将输入输入到字符串中,几乎可以肯定您最终会遇到安全问题。想想如果有人可以添加x'$(rm /somethingimportant)'y到您的文件模式列表中会发生什么。

对于动态构建命令的情况,bash 数组是更好的选择。使用如下方法:

namepatterns=(-name xxxx)
namepatterns+=(-o -name yyyyy -o -name "*.txt") # quotes prevent wildcard expansion
while read pattern; do
    namepatterns+=(-o -name "$pattern")
done <patternfile.txt

find /etc "${namepatterns[@]}"

"${array[@]}"习语将数组的每个元素视为一个 shell 词,而不会出现未加引号的变量引用会遭受的任何有问题的解析(单词拆分、通配符扩展)。

顺便说一句,在上面的例子中,我稍微作弊了一点,将第一个-name xxxx主元素添加到数组中,而-o前面没有一个。如果你完全在循环中构建数组,这会更棘手:

namepatterns=()
while read pattern; do
    namepatterns+=(-o -name "$pattern")
done <patternfile.txt
# At this point the array starts with "-o" -- not what you want
# So use array slicing to remove the first element:
namepatterns=("${namepatterns[@]:1}")

find /etc "${namepatterns[@]}"

BashFAQ #50:我尝试将命令放入变量中,但复杂的情况总是失败!有关构建和存储命令的更多讨论和选项。

答案3

尝试

eval find /etc $SEARCH
  • eval 将会评估变量扩展后的行

答案4

尝试-name这样的选项:

SEARCH="shells"; find /etc -name $SEARCH

看一眼这个问题一些选项。

相关内容