有一个选项可用于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
命令中。