我有一个包含大约1000个文件名的列表,可以在目录及其子目录下进行搜索.有数百个子目录超过1,000,000个文件.以下命令将运行find 1000次:
cat filelist.txt | while read f; do find /dir -name $f; done
Run Code Online (Sandbox Code Playgroud)
有更快的方法吗?
huo*_*uon 13
如果filelist.txt
每行有一个文件名:
find /dir | grep -f <(sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt)
Run Code Online (Sandbox Code Playgroud)
(该-f
选项意味着grep搜索给定文件中的所有模式.)
说明<(sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt)
:
它<( ... )
被称为进程替换,并且有点类似于$( ... )
.这种情况相当于(但使用流程替换更整洁,可能更快一些):
sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt > processed_filelist.txt
find /dir | grep -f processed_filelist.txt
Run Code Online (Sandbox Code Playgroud)
调用sed
运行命令s@^@/@
,s/$/$/
并s/\([\.[\*]\|\]\)/\\\1/g
在每行上filelist.txt
打印出来.这些命令将文件名转换为可以更好地与grep一起使用的格式.
s@^@/@
意思是/
在每个文件名之前加上一个.(^
正则表达式中的"行首")s/$/$/
意味着$
在每个文件名的末尾加上一个.(第一个$
意思是"行尾",第二个只是一个文字$
,然后由grep解释为"行尾").这两个规则的组合意味着grep只会查找匹配.../<filename>
,因此a.txt
匹配./a.txt.backup
或匹配./abba.txt
.
s/\([\.[\*]\|\]\)/\\\1/g
\
在每次出现之前放置一个.
[
]
或*
.Grep使用正则表达式并且这些字符被认为是特殊的,但是我们希望它们是普通的,所以我们需要转义它们(如果我们没有转义它们,那么文件名就像a.txt
匹配文件一样abtxt
).
举个例子:
$ cat filelist.txt
file1.txt
file2.txt
blah[2012].txt
blah[2011].txt
lastfile
$ sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt
/file1\.txt$
/file2\.txt$
/blah\[2012\]\.txt$
/blah\[2011\]\.txt$
/lastfile$
Run Code Online (Sandbox Code Playgroud)
然后Grep在搜索输出时使用该输出的每一行作为模式find
.
小智 5
如果filelist.txt
是简单列表:
$ find /dir | grep -F -f filelist.txt
Run Code Online (Sandbox Code Playgroud)
如果filelist.txt
是模式列表:
$ find /dir | grep -f filelist.txt
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
24491 次 |
最近记录: |