Shell:在目录下查找列表中的文件

我有一个列表,其中包含大约1000个文件名在一个目录及其子目录下进行search。 有数百个文件超过1,000,000个的子目录。 以下命令将运行1000次查找:

cat filelist.txt | while read f; do find /dir -name $f; done 

有更快的方法来做到这一点?

Solutions Collecting From Web of "Shell:在目录下查找列表中的文件"

如果filelist.txt每行只有一个文件名:

 find /dir | grep -f <(sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt) 

-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 

sed的调用在filelist.txt每行上运行s@^@/@s/$/$/s/\([\.[\*]\|\]\)/\\\1/g filelist.txt并打印出来。 这些命令将文件名转换成可以更好地使用grep的格式。

  • s@^@/@表示在每个文件名之前放一个/ 。 ( ^表示正则表达式中的“行首”)
  • s/$/$/表示在每个文件名末尾放一个$ 。 (第一个$表示“行结束”,第二个只是一个文字$ ,然后被grep解释为“行尾”)。

这两个规则的组合意味着grep只会查找类似于.../<filename>匹配./a.txt.backup ,以便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$ 

然后,Grep在搜索find的输出时,使用该输出的每一行作为模式。

在while循环中使用xargs(1)可以比在bash中快一点。

喜欢这个

 xargs -a filelist.txt -I filename find /dir -name filename 

请注意,如果filelist.txt中的文件名包含空格,请阅读关于此问题的xargs(1)页说明部分中的第二段。

基于一些假设的改进。 例如,a.txt位于filelist.txt中,您可以确保/ dir中只有一个a.txt。 然后你可以告诉find(1)在发现实例时提前退出。

 xargs -a filelist.txt -I filename find /dir -name filename -print -quit 

解决方案 您可以预先处理filelist.txt文件,将其作为find(1)参数列表。 这将减少find(1)调用:

 find /dir -name 'a.txt' -or -name 'b.txt' -or -name 'c.txt' 

我并不完全确定这个问题,但是我在试图找到一种方法来发现13000个文件中有4个未能复制的情况下来到这个页面。

这两个答案都没有为我做,所以我这样做:

 cp file-list file-list2 find dir/ >> file-list2 sort file-list2 | uniq -u 

结果列出了我需要的4个文件。

这个想法是结合这两个文件列表来确定唯一的条目。 sort是用来使重复的条目彼此相邻这是唯一的方式将uniq过滤出来。

如果filelist.txt是一个普通的列表:

 $ find /dir | grep -F -f filelist.txt 

如果filelist.txt是一个模式列表:

 $ find /dir | grep -f filelist.txt