使用 find 命令从文件中搜索多个模式

使用 find 命令从文件中搜索多个模式

有一个选项可用于grep -f MY_FILE让它搜索从文件中获取的模式,而不是直接在命令行上指定。

是否有一个选项可以对该命令执行类似的操作find并让它读取输入文件中要搜索的模式?

答案1

find似乎没有内置这样的功能,但您可以使用文件中的参数xargs构造多个命令,例如:find

xargs -a patterns.txt -I% find Pictures/ -name %

其中patterns.txt是适合过滤器的模式列表-name,每行一个模式。请注意,其中没有前导/尾随空格,因为它们将包含在模式中。例如:

*.jpg
2018-06-*
*foo*
unicorn.png

笔记:虽然这个答案看起来很简单和优雅,但评论中正确地指出它有几个缺点:

对于大型文件夹或许多模式来说,性能不是很好,因为它会find针对文件中的每个模式运行一次,从而导致它重复扫描整个搜索文件夹。

因此,如果您有多个可能重叠的模式(如*.jpg*foo*),则与多个模式匹配的文件将在结果中出现多次。如果您无论如何都只打印名称,则可以通过管道传输输出sort -u以删除重复项,但如果您删除这些结果或-exec对它们运行任何命令,则这可能更不受欢迎。

如果这些缺点中的任何一个对您的使用情况造成问题,也许最好选择其中一种替代答案。

命令解释:

  • xargs将读取参数列表并使用它们构建和运行新的命令行。
  • -a patterns.txt告诉它从该文件而不是标准输入读取。
  • -I%告诉它不要简单地将读取的参数附加到命令行末尾,而是%用一个参数替换命令行中提供的字符。这意味着为每个输入参数创建并运行一个单独的命令。
  • find Pictures/ -name %是我们要插入参数的命令行,替换%。这里不需要引用,因为xargs会确保插入的每个参数都被视为单个标记,而不会单独拆分。当然,您可以Pictures/用自己的搜索目录替换 ,也可以使用除 之外的不同和/或更多过滤器-name。因为我们使用插入选项,所以您还可以将类似操作附加-exec ...到命令末尾。

答案2

您可以简单地使用 从文件内容中创建一个正则表达式paste -sd'|' bar

find ~/foo -regextype egrep -regex "^.*/($(paste -sd'|' bar))$"

正则表达式将是"^.*/(a|b)$"

答案3

不久前,我做了一个回答-regex使用中的标志组合多个模式find。基于此,我们可以编写一个小脚本或函数来完成相同的工作,但从文件中构建模式列表。

#!/bin/bash

read_file(){
    local full_pattern=""
    while IFS= read -r pattern; do
        if [ -z "$full_pattern"  ];then
            full_pattern="$pattern"
            continue
        fi
        full_pattern="$full_pattern\|$pattern"
    done < "$1"
    echo "$full_pattern"
}

fp=$(read_file "$1" )
find "$2" -type f -regex ".*\($fp\).*$" 

它的作用是:

  • 我们将脚本调用为findf.sh input.txt /etc,其中第一个位置参数是带有模式的文件,第二个位置参数是要搜索的目录。.如果省略目录参数,GNU find 会假定目录,因此$2不需要。
  • 该函数read_file读取作为脚本第一个位置参数的输入文件。这将为标志建立一个模式-regex
  • 该模式被回送到脚本的“主”块,并保存到fp变量中,然后传递到find命令中。

相关内容