Подтвердить что ты не робот

Список каталогов с заданной глубиной в Python

Я хочу, чтобы функция возвращала список с каталогами с указанным путем и фиксированной глубиной и вскоре поняла несколько альтернатив. Я использую os.walk довольно много, но код стал выглядеть уродливым при подсчете глубины и т.д.

Что на самом деле является самой "опрятной" реализацией?

4b9b3361

Ответ 1

Если глубина зафиксирована, glob является хорошей идеей:

import glob,os.path
filesDepth3 = glob.glob('*/*/*')
dirsDepth3 = filter(lambda f: os.path.isdir(f), filesDepth3)

В противном случае это не должно быть слишком сложно использовать os.walk:

import os,string
path = '.'
path = os.path.normpath(path)
res = []
for root,dirs,files in os.walk(path, topdown=True):
    depth = root[len(path) + len(os.path.sep):].count(os.path.sep)
    if depth == 2:
        # We're currently two directories in, so all subdirs have depth 3
        res += [os.path.join(root, d) for d in dirs]
        dirs[:] = [] # Don't recurse any deeper
print(res)

Ответ 2

Это не совсем аккуратно, но под UNIX-подобной ОС вы также можете полагаться на системный инструмент, такой как "найти", и просто выполнять его как внешнюю программу, например:

from subprocess import call
call(["find", "-maxdepth", "2", "-type", "d"])

Затем вы можете перенаправить вывод на некоторую строковую переменную для дальнейшей обработки.

Ответ 3

Мне очень нравится ответ phihag. Я адаптировал его в соответствии с моими потребностями.

import fnmatch,glob
def fileNamesRetrieve( top, maxDepth, fnMask  ):
    someFiles = []
    for d in range( 1, maxDepth+1 ):
        maxGlob = "/".join( "*" * d )
        topGlob = os.path.join( top, maxGlob )
        allFiles = glob.glob( topGlob )
        someFiles.extend( [ f for f in allFiles if fnmatch.fnmatch( os.path.basename( f ), fnMask ) ] )
    return someFiles

Я думаю, я мог бы сделать его генератором с чем-то вроде этого:

def fileNamesRetrieve( top, maxDepth, fnMask  ):
    for d in range( 1, maxDepth+1 ):
        maxGlob = "/".join( "*" * d )
        topGlob = os.path.join( top, maxGlob )
        allFiles = glob.glob( topGlob )
        if fnmatch.fnmatch( os.path.basename( f ), fnMask ):
            yield f

Признание критики.

Ответ 4

Вот реализация pathlib:

from pathlib import Path

def get_files(path, mask, depth):
    for i in range(1, depth + 1):
        for f in Path(path).glob('/'.join('*' * i) + '/' + mask):
            yield f

Пример использования:

for i in get_files('testdir', '*.txt', 1):
    print(i)
>>>
testdir/a/a.txt
testdir/b/b.txt
testdir/c/c.txt

for i in get_files('testdir', '*.txt', 2):
    print(i)
>>>
testdir/a/a.txt
testdir/b/b.txt
testdir/c/c.txt
testdir/a/aa/aa.txt
testdir/b/bb/bb.txt
testdir/c/cc/cc.txt