find / foo / bar *而不是find / foo -name“bar *”

时间:2014-01-17 14:30:53

标签: bash

通常建议使用

find /foo -name "bar*"

bar中查找以/foo开头的所有文件。使用

不是更简单
find /foo/bar*

?我理解bash在最后一个示例中扩展了/foo/bar*而不是find本身,但是有任何风险吗?

我的用例是我想将命令存储到变量中find,例如

FINDSTRING='/foo -name "bar*"'
FILES=`find $FINDSTRING`

不起作用,或

FINDSTRING='/foo -name bar*'
FILES=`find $FINDSTRING`

如果当前目录中有bar*文件但

,则无效
FINDSTRING='/foo/bar*'
FILES=`find $FINDSTRING`

确实有效。

5 个答案:

答案 0 :(得分:4)

使用数组存储命令的选项,而不是扁平字符串:

find_options=( /foo -name "bar*" )
files=$( find "${find_options[@]}" )

如果这些文件名包含空格,尝试将文件列表存储在字符串中还有其他问题,但这是另一个问题。

答案 1 :(得分:2)

不是将整个find命令存储在变量中,而是考虑在这样的变量中存储路径和glob模式:

fpath='/foo'
fname='bar*'

然后运行您的find命令:

find "$fpath" -name "$fname"

答案 2 :(得分:0)

FINDSTRING='/foo -name bar*'
FILES=`find $FINDSTRING`

在此示例中,bash正在展开通配符(*)而不是findfind因此尝试将文件列表评估为名称模式文件。所以它不起作用......

否则,-name选项允许我们使用特定模式的名称文件,例如:

sudo find / -name "[0-9]*"

答案 3 :(得分:0)

  如果当前目录中有bar *文件,则

不起作用,但

您可以通过在参数周围使用单引号来阻止Bash扩展*中的FINDSTRING来解决此问题:

FINDSTRING="/foo -name 'bar*'"

不要让Bash进行扩展(如果你这样做,那么使用find的重点是什么,因为Bash已经生成了匹配文件列表?)

答案 4 :(得分:0)

find /foo/bar*仅搜索/ foo目录顶层以“bar”开头的文件名。例如,如果/foo/quux/bar.txt存在,find /foo -name "bar*"会找到它,但find /foo/bar*不会找到它。

现在,至于将命令存储在变量中,简短的答案是你不能(至少在一个普通的变量中)。有一些选项可以执行类似于将其存储在变量中的选项,但是您应该使用哪个选项取决于为什么要将其存储在变量中。 BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!涵盖了这一点,但这里是简短摘要。

  • 如果您没有充分的理由在执行变量之前将命令存储在变量中,那么只需。存储&检索命令可能很麻烦,如果没有充分理由可以跳过整个混乱并直接执行命令。

  • 如果需要动态构建命令,可以将命令(或只是其参数)存储在数组中(如chepner建议的那样):

    find_options=(/foo -name "bar*")
    files="$(find "${find_options[@]}")"
    

    正如chepner也指出的那样,如果文件名中包含空格,则会失败。你真的应该把文件名存储为一个数组:

    find_options=(/foo -name "bar*")
    
    files=()
    while IFS= read -r -d '' file; do
        files+=("file")
    done < <(find "${find_options[@]}")
    
    dostuffwith "${files[@]}"
    

    (见BashFAQ #20: How can I find and safely handle file names containing newlines, spaces or both?。)

  • 如果您只是想重复使用该命令而不是每次都写出来,可以将命令转换为函数:

    find_bar() {
        find /foo -name "bar*"
    }
    
    files=()
    while IFS= read -r -d '' file; do
        files+=("file")
    done < <(find_bar)
    
    dostuffwith "${files[@]}"