从存储在文件f
中的文件名列表中,找到dir
下每个文件名的相对路径的最佳方法是什么,将此新列表输出到文件p
?我目前正在使用以下内容:
while read name
do
find dir -type f -name "$name" >> p
done < f
对于大型列表或大型目录树来说太慢了。
编辑:一些数字:
dir
下的目录数:1870 dir
下的文件数:80622 f
中的文件名数:73487 f
中列出的所有文件都存在于dir
下。
答案 0 :(得分:3)
下面的python代码可以解决这个问题。关键是运行find一次并将输出存储在hashmap中,以提供O(1)方式从file_name获取文件名的路径列表。
#!/usr/bin/env python
import os
file_names = open("f").readlines()
file_paths = os.popen("find . -type f").readlines()
file_names_to_paths = {}
for file_path in file_paths:
file_name = os.popen("basename "+file_path).read()
if file_name not in file_names_to_paths:
file_names_to_paths[file_name] = [file_path]
else:
file_names_to_paths[file_name].append(file_path) # duplicate file
out_file = open("p", "w")
for file_name in file_names:
if file_names_to_paths.has_key(file_name):
for path in file_names_to_paths[file_name]:
out_file.write(path)
答案 1 :(得分:2)
试试这个perl one-liner
perl -e '%H=map{chomp;$_=>1}<>;sub R{my($p)=@_;map R($_),<$p/*> if -d$p;($b=$p)=~s|.*/||;print"$p\n" if$H{$b}}R"."' f
1-创建一个键值为文件名的hashmap:%H = map {chomp; $ _ =&gt; 1}&lt;&gt;
2-定义遍历目录的递归子例程:sub R {}
2.1-目录的重复调用:map R($ _),if -d $ p
2.2-从路径中提取文件名:($ b = $ p)=〜s |。* / ||
2.3-打印如果hashmap包含文件名:print“$ p \ n”如果$ H {$ b}
3-用路径当前目录调用R:R“。”
编辑:遍历隐藏目录(。*)
perl -e '%H=map{chomp;$_=>1}<>;sub R{my($p)=@_;map R($_),grep !m|/\.\.?$|,<$p/.* $p/*> if -d$p;($b=$p)=~s|.*/||;print"$p\n" if$H{$b}}R"."' f
答案 2 :(得分:1)
我认为这应该可以解决问题:
xargs locate -b < f | grep ^dir > p
编辑:我想不出一种简单的方法可以将dir/*/
添加到文件名列表中,否则您可以直接将其传递给xargs locate
。< / p>
答案 3 :(得分:0)
根据目录树被视为匹配的百分比,找到每个文件可能会更快,然后查找匹配的文件:
find "$dir" -type f | grep -f <( sed 's+\(.*\)+/\1$+' "$f" )
sed
命令将您的文件名列表预处理为正则表达式,该表达式只匹配路径末尾的全名。
答案 4 :(得分:0)
这是使用bash和grep
的替代方法#!/bin/bash
flist(){
for x in "$1"/*; do #*/ for markup
[ -d "$x" ] && flist $x || echo "$x"
done
}
dir=/etc #the directory you are searching
list=$(< myfiles) #the file with file names
#format the list for grep
list="/${list//
/\$\|/}"
flist "$dir" | grep "$list"
...如果你需要完整的posix shell兼容性(busybox ash,hush等...)用chepner的sed变种替换$ list子串操作,用$(cat file)替换$(&lt; file)