> 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 将会评估变量扩展后的行