我有一个包含大约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 次 |
| 最近记录: |