3

Antには、ファイルのグループを選択するための優れた方法があります。最も便利なのは、**を使用してディレクトリツリーを示すことです。例えば

**/CVS/*            # All files immediately under a CVS directory.
mydir/mysubdir/**   # All files recursively under mysubdir

その他の例はここで見ることができます:

http://ant.apache.org/manual/dirtasks.html

これをPythonでどのように実装して、次のようなことができるようにしますか?

files = get_files("**/CVS/*")
for file in files:
    print file

=>
CVS/Repository
mydir/mysubdir/CVS/Entries
mydir/mysubdir/foo/bar/CVS/Entries
4

6 に答える 6

4

申し訳ありませんが、これは OP からかなり時間が経っています。まさにこれを行う Python パッケージをリリースしました。これは Formic と呼ばれ、PyPI Cheeseshopで入手できます。Formic を使用すると、次の方法で問題を解決できます。

import formic
fileset = formic.FileSet(include="**/CVS/*", default_excludes=False)
for file_name in fileset.qualified_files():
    print file_name

少し複雑な点が 1 つあります。default_excludes です。Formic は、Ant と同様に、デフォルトで CVS ディレクトリを除外します (ほとんどの場合、ビルドのためにそれらからファイルを収集するのは危険です)。質問に対するデフォルトの回答では、ファイルはありません。default_excludes=False を設定すると、この動作が無効になります。

于 2012-05-15T08:39:01.297 に答える
3

に出くわすとすぐに、**ディレクトリ構造全体を再帰する必要があるため、その時点で最も簡単な方法は、ディレクトリを os.walk で反復処理し、パスを作成してから確認することだと思います柄が合っていれば。おそらく、次のような方法で正規表現に変換できます。

def glob_to_regex(pat, dirsep=os.sep):
    dirsep = re.escape(dirsep)
    print re.escape(pat)
    regex = (re.escape(pat).replace("\\*\\*"+dirsep,".*")
                           .replace("\\*\\*",".*")
                           .replace("\\*","[^%s]*" % dirsep)
                           .replace("\\?","[^%s]" % dirsep))
    return re.compile(regex+"$")

(ただし、これは完全な機能ではないことに注意してください[a-z]。たとえば、スタイル glob パターンはサポートされていませんが、おそらく追加される可能性があります)。(最初のmatch は、 matchingの\*\*/ようなケースをカバーするだけでなく、末尾でのみ一致する必要がある場合にも対応します。)\*\*/CVS./CVS\*\*

ただし、パターンを処理していないときに、現在のディレクトリの下のすべてを再帰したくないことは明らか**なので、2段階のアプローチが必要になると思います。私は以下を実装しようとはしていません。おそらくいくつかのまれなケースがありますが、うまくいくはずです:

  1. ディレクトリ区切り記号でパターンを分割します。すなわちpat.split('/') -> ['**','CVS','*']

  2. ディレクトリを再帰的に調べて、このレベルのパターンの関連部分を調べます。すなわち。n levels deep -> look at pat[n].

  3. pat[n] == '**'上記の戦略に切り替える場合:

    • でパターンを再構築するdirsep.join(pat[n:])
    • で正規表現に変換しますglob\_to\_regex()
    • 現在のディレクトリを再帰的os.walkに通過し、開始したレベルに相対的なパスを構築します。パスが正規表現と一致する場合は、それを生成します。
  4. pat が一致せず"**"、それがパターンの最後の要素である場合、一致するすべてのファイル/ディレクトリを生成しますglob.glob(os.path.join(curpath,pat[n]))

  5. pat が一致せず"**"、それがパターンの最後の要素ではない場合は、ディレクトリごとに (グロブで) 一致するかどうかを確認しpat[n]ます。もしそうなら、深さをインクリメントして、それを再帰します(したがって、それは になりますpat[n+1]

于 2008-10-02T16:07:32.973 に答える
2

os.walkあなたの友達です。Python マニュアル ( https://docs.python.org/2/library/os.html#os.walk ) の例を見て、そこから何かを構築してみてください。

取得したファイル名に対して" " を一致**/CVS/*させるには、次のようにします。

def match(pattern, filename):
    if pattern.startswith("**"):
        return fnmatch.fnmatch(file, pattern[1:])
    else:
        return fnmatch.fnmatch(file, pattern)

ではfnmatch.fnmatch、「*」はすべて (スラッシュを含む) に一致します。

于 2008-10-02T11:42:20.350 に答える
1

'waf'ビルドシステムのソースコードに実装があります。 http://code.google.com/p/waf/source/browse/trunk/waflib/Node.py?r=10755#471 これは、独自のライブラリにラップする必要がありますか?

于 2010-12-24T10:34:20.340 に答える
0

これにはos.walkが最適です。以下の例を .svn で実行したのは、.svn が便利だったからです。

import re

for (dirpath, dirnames, filenames) in os.walk("."):
    if re.search(r'\.svn$', dirpath):
        for file in filenames:
            print file
于 2008-10-02T14:47:57.440 に答える
0

うん。最善の策は、すでに提案されているように、「os.walk」を使用することです。または、' glob ' および ' fnmatch ' モジュールの周りにラッパーを記述します。

于 2008-10-02T11:54:28.323 に答える