3

ファイルに保存されているファイル名のリストから、この新しいリストをファイルに出力して、f下の各ファイル名の相対パスを見つける最良の方法は何ですか?私は現在次のものを使用しています:dirp

while read name
do
    find dir -type f -name "$name" >> p
done < f

これは、大きなリストや大きなディレクトリツリーには遅すぎます。

編集:いくつかの数字:

  • 下のディレクトリの数dir:1870
  • 下のファイル数dir:80622
  • のファイル名の数f:73487

にリストされているすべてのファイルは、fの下に存在しdirます。

4

5 に答える 5

3

次の Python コードは、このトリックを実行します。重要なのは、find を 1 回実行し、出力をハッシュマップに格納して、file_name からファイル名のパスのリストに到達する O(1) 方法を提供することです。

#!/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)
于 2012-09-06T12:06:05.583 に答える
2

このperlワンライナーをお試しください

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-キーがファイル名であるハッシュマップを作成します:%H = map {chomp; $ _ => 1} <>

2-ディレクトリをトラバースする再帰サブルーチンを定義します:sub R {}

2.1-ディレクトリの再帰呼び出し:-d $ pの場合、マップR($ _)

2.2-パスからファイル名を抽出します:($ b = $ p)=〜s|。*/ ||

2.3-ハッシュマップにファイル名が含まれている場合は印刷:print "$ p \ n" if $ 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
于 2012-09-06T12:21:41.537 に答える
1

これでうまくいくはずだと思います:

xargs locate -b < f | grep ^dir > p

編集:ファイル名のリストにプレフィックスを付ける簡単な方法は考えられません。dir/*/それ以外の場合は、直接に渡すことができますxargs locate

于 2012-09-06T11:49:10.140 に答える
0

ディレクトリ ツリーの何パーセントが一致すると見なされるかに応じて、すべてのファイルを検索してから、一致するファイルを grep する方が高速な場合があります。

find "$dir" -type f | grep -f <( sed 's+\(.*\)+/\1$+' "$f" )

このsedコマンドは、ファイル名のリストを正規表現に前処理し、パスの末尾にある完全な名前のみに一致させます。

于 2012-09-06T12:25:53.820 に答える
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 シェル準拠 (busybox ash、hush など) が必要な場合は、$list 部分文字列操作を chepner の sed のバリアントに置き換え、$(< file) を $(cat file) に置き換えます

于 2012-09-06T15:35:08.343 に答える