IT

목록의 파일을 재귀 하위 폴더 검색 및 반환하려면 어떻게 해야 합니까?

itgroup 2023. 1. 12. 22:11
반응형

목록의 파일을 재귀 하위 폴더 검색 및 반환하려면 어떻게 해야 합니까?

메인폴더내의 서브폴더를 재귀적으로 검색해, 특정의 파일 타입으로 리스트를 작성하는 스크립트를 작성하고 있습니다.대본에 문제가 있어요.현재 다음과 같이 설정되어 있습니다.

for root, subFolder, files in os.walk(PATH):
    for item in files:
        if item.endswith(".txt") :
            fileNamePath = str(os.path.join(root,subFolder,item))

는 '이러다'가subFolder변수가 ITEM 파일이 있는 폴더가 아닌 하위 폴더 목록을 가져옵니다.이전에 하위 폴더에 대한 for 루프를 실행하여 경로의 첫 번째 부분에 참여하려고 했는데, 그 전에 제안 사항이 있는지 다시 한 번 확인해보려고 합니다.

'어울리다'를하셔야 합니다.dirpath을 「」라고 부릅니다.root . 。dirnames않는 경우 할 수 제공됩니다.os.walk을 하다

import os
result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(PATH) for f in filenames if os.path.splitext(f)[1] == '.txt']

편집:

투표 에, .glob는 내선번호로 선택하는 데 더 좋은 도구입니다.

import os
from glob import glob
result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))]

제너레이터 버전도

from itertools import chain
result = (chain.from_iterable(glob(os.path.join(x[0], '*.txt')) for x in os.walk('.')))

Python 3.4+용 Edit2

from pathlib import Path
result = list(Path(".").rglob("*.[tT][xX][tT]"))

Python 3.5에서 변경: "**"를 사용한 재귀 글로브 지원.

glob.glob()새로운 재귀 파라미터를 취득했습니다.

것을 .txtmy_path (서브디르 포함):

import glob

files = glob.glob(my_path + '/**/*.txt', recursive=True)

# my_path/     the dir
# **/       every file and dir under my_path
# *.txt     every file that ends with '.txt'

반복기가 필요한 경우 iglob을 대신 사용할 수 있습니다.

for file in glob.iglob(my_path, recursive=True):
    # ...

이 솔루션은 제가 생각할 수 있는 솔루션 중 가장 빠른 것 같습니다.또, 그 어느 솔루션보다도 고속입니다.

  • 또한 기본적으로 모든 중첩된 하위 폴더 목록이 무료로 제공됩니다.
  • 몇 가지 다른 내선번호를 검색할 수 있습니다.
  • 할 수도 .f.path로로 합니다.f.name(하위 폴더에 대해서는 변경하지 마십시오!).

Args:dir: str, ext: list.
함수는 다음 두 가지 목록을 반환합니다.subfolders, files.

자세한 속도는 아래를 참조하십시오.

def run_fast_scandir(dir, ext):    # dir: str, ext: list
    subfolders, files = [], []

    for f in os.scandir(dir):
        if f.is_dir():
            subfolders.append(f.path)
        if f.is_file():
            if os.path.splitext(f.name)[1].lower() in ext:
                files.append(f.path)


    for dir in list(subfolders):
        sf, f = run_fast_scandir(dir, ext)
        subfolders.extend(sf)
        files.extend(f)
    return subfolders, files


subfolders, files = run_fast_scandir(folder, [".jpg"])

사이즈가 는, 「」를 .sizes add " " " 。f.stat().st_sizeMiB를 표시하기 위해 이렇게 .

sizes.append(f"{f.stat().st_size/1024/1024:.0f} MiB")

속도 분석

모든 하위 폴더 및 기본 폴더 내에 특정 파일 확장자를 가진 모든 파일을 가져오는 다양한 방법을 제공합니다.

tl;dr:

  • fast_scandiros.walk를 한 다른 솔루션보다 .
  • os.walk2번으로 나누다
  • 를 사용합니다.glob처리 속도가 크게 느려집니다.
  • 자연 정렬을 사용하는 결과는 없습니다.즉, 결과는 1, 10, 2와 같이 정렬됩니다.자연스러운 정렬(1, 2, 10)을 얻으려면 다음 항목을 확인하십시오.

결과:

fast_scandir    took  499 ms. Found files: 16596. Found subfolders: 439
os.walk         took  589 ms. Found files: 16596
find_files      took  919 ms. Found files: 16596
glob.iglob      took  998 ms. Found files: 16596
glob.glob       took 1002 ms. Found files: 16596
pathlib.rglob   took 1041 ms. Found files: 16596
os.walk-glob    took 1043 ms. Found files: 16596

갱신일 : 2022-07-20 (Py)3.10.1*.pdf)

glob.iglob      took 132 ms. Found files: 9999
glob.glob       took 134 ms. Found files: 9999
fast_scandir    took 331 ms. Found files: 9999. Found subfolders: 9330
os.walk         took 695 ms. Found files: 9999
pathlib.rglob   took 828 ms. Found files: 9999
find_files      took 949 ms. Found files: 9999
os.walk-glob    took 1242 ms. Found files: 9999

W7x64, Python 3.8.1, 20.(부분 서브폴더 16596 파일.
find_files는 https://stackoverflow.com/a/45646357/2441026 에서 취득한 것으로, 몇개의 내선번호를 검색할 수 있습니다.
fast_scandir는 내가 작성한 것으로, 서브폴더 리스트도 반환됩니다.할 수 한 확장자 가 포함되어 ).if ... == ".jpg"큰 차이는 없었다).


# -*- coding: utf-8 -*-
# Python 3


import time
import os
from glob import glob, iglob
from pathlib import Path


directory = r"<folder>"
RUNS = 20


def run_os_walk():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [os.path.join(dp, f) for dp, dn, filenames in os.walk(directory) for f in filenames if
                  os.path.splitext(f)[1].lower() == '.jpg']
    print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found files: {len(fu)}")


def run_os_walk_glob():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [y for x in os.walk(directory) for y in glob(os.path.join(x[0], '*.jpg'))]
    print(f"os.walk-glob\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found files: {len(fu)}")


def run_glob():
    a = time.time_ns()
    for i in range(RUNS):
        fu = glob(os.path.join(directory, '**', '*.jpg'), recursive=True)
    print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found files: {len(fu)}")


def run_iglob():
    a = time.time_ns()
    for i in range(RUNS):
        fu = list(iglob(os.path.join(directory, '**', '*.jpg'), recursive=True))
    print(f"glob.iglob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found files: {len(fu)}")


def run_pathlib_rglob():
    a = time.time_ns()
    for i in range(RUNS):
        fu = list(Path(directory).rglob("*.jpg"))
    print(f"pathlib.rglob\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found files: {len(fu)}")


def find_files(files, dirs=[], extensions=[]):
    # https://stackoverflow.com/a/45646357/2441026

    new_dirs = []
    for d in dirs:
        try:
            new_dirs += [ os.path.join(d, f) for f in os.listdir(d) ]
        except OSError:
            if os.path.splitext(d)[1].lower() in extensions:
                files.append(d)

    if new_dirs:
        find_files(files, new_dirs, extensions )
    else:
        return


def run_fast_scandir(dir, ext):    # dir: str, ext: list
    # https://stackoverflow.com/a/59803793/2441026

    subfolders, files = [], []

    for f in os.scandir(dir):
        if f.is_dir():
            subfolders.append(f.path)
        if f.is_file():
            if os.path.splitext(f.name)[1].lower() in ext:
                files.append(f.path)


    for dir in list(subfolders):
        sf, f = run_fast_scandir(dir, ext)
        subfolders.extend(sf)
        files.extend(f)
    return subfolders, files



if __name__ == '__main__':
    run_os_walk()
    run_os_walk_glob()
    run_glob()
    run_iglob()
    run_pathlib_rglob()


    a = time.time_ns()
    for i in range(RUNS):
        files = []
        find_files(files, dirs=[directory], extensions=[".jpg"])
    print(f"find_files\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found files: {len(files)}")


    a = time.time_ns()
    for i in range(RUNS):
        subf, files = run_fast_scandir(directory, [".jpg"])
    print(f"fast_scandir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found files: {len(files)}. Found subfolders: {len(subf)}")

루이의 목록 이해도를 다른 사람이 이해할 수 없을 때를 대비해서 중첩된 것으로 번역하겠습니다.

result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))]

다음과 같아야 합니다.

import glob
import os

result = []

for x in os.walk(PATH):
    for y in glob.glob(os.path.join(x[0], '*.txt')):
        result.append(y)

목록 이해 및 os.walk 및 glob 함수대한 문서입니다.

★★★★★pathlib라이브러리는 이를 한 줄로 단순화합니다.

from pathlib import Path
result = list(Path(PATH).glob('**/*.txt'))

제너레이터 버전을 사용할 수도 있습니다.

from pathlib import Path
for file in Path(PATH).glob('**/*.txt'):
    pass

값은 반환됩니다.Path 것에 할 수 또, 할 수도 있습니다.file.name.

원래 솔루션은 거의 정확했지만 변수 "root"은 반복 경로 지정 시 동적으로 업데이트됩니다.os.walk()는 재귀 생성기입니다.의 각 태플 세트(root, subFolder, files)는 설정한 대로 특정 루트에 대한 것입니다.

예.

root = 'C:\\'
subFolder = ['Users', 'ProgramFiles', 'ProgramFiles (x86)', 'Windows', ...]
files = ['foo1.txt', 'foo2.txt', 'foo3.txt', ...]

root = 'C:\\Users\\'
subFolder = ['UserAccount1', 'UserAccount2', ...]
files = ['bar1.txt', 'bar2.txt', 'bar3.txt', ...]

...

전체 목록을 인쇄하기 위해 코드를 약간 수정했습니다.

import os
for root, subFolder, files in os.walk(PATH):
    for item in files:
        if item.endswith(".txt") :
            fileNamePath = str(os.path.join(root,item))
            print(fileNamePath)

이게 도움이 됐으면 좋겠네요!

편집: (페이트백 기준)

실제로 "root"에 있는 모든 하위 폴더이므로 OP가 하위 폴더 변수를 잘못 이해하거나 레이블을 잘못 지정했습니다.이 때문에 OP에서는 os.path.join(str, list, str)을 실행하려고 합니다.이 작업은 아마 예상대로 되지 않을 것입니다.

알기 쉽게 하기 위해 다음 라벨 방식을 사용해 보십시오.

import os
for current_dir_path, current_subdirs, current_files in os.walk(RECURSIVE_ROOT):
    for aFile in current_files:
        if aFile.endswith(".txt") :
            txt_file_path = str(os.path.join(current_dir_path, aFile))
            print(txt_file_path)

가장 비단어적인 대답은 아니지만, 재미로 여기에 두겠습니다. 왜냐하면 이것은 재귀에 대한 깔끔한 교훈이기 때문입니다.

def find_files( files, dirs=[], extensions=[]):
    new_dirs = []
    for d in dirs:
        try:
            new_dirs += [ os.path.join(d, f) for f in os.listdir(d) ]
        except OSError:
            if os.path.splitext(d)[1] in extensions:
                files.append(d)

    if new_dirs:
        find_files(files, new_dirs, extensions )
    else:
        return

에는 두의 폴더가 .root ★★★★★★★★★★★★★★★★★」root2

mender@multivax ]ls -R root root2
root:
temp1 temp2

root/temp1:
temp1.1 temp1.2

root/temp1/temp1.1:
f1.mid

root/temp1/temp1.2:
f.mi  f.mid

root/temp2:
tmp.mid

root2:
dummie.txt temp3

root2/temp3:
song.mid

찾고 요..txt 모든 「」의 「」를 참조하십시오..mid중 하면 됩니다.」를 할 수 .

files = []
find_files( files, dirs=['root','root2'], extensions=['.mid','.txt'] )
print(files)

#['root2/dummie.txt',
# 'root/temp2/tmp.mid',
# 'root2/temp3/song.mid',
# 'root/temp1/temp1.1/f1.mid',
# 'root/temp1/temp1.2/f.mid']

이 방법으로 절대 경로 파일 목록을 반환할 수 있습니다.

def list_files_recursive(path):
    """
    Function that receives as a parameter a directory path
    :return list_: File List and Its Absolute Paths
    """

    import os

    files = []

    # r = root, d = directories, f = files
    for r, d, f in os.walk(path):
        for file in f:
            files.append(os.path.join(r, file))

    lst = [file for file in files]
    return lst


if __name__ == '__main__':

    result = list_files_recursive('/tmp')
    print(result)

재귀는 Python 3.5에서는 새로운 기능이기 때문에 Python 2.7에서는 동작하지 않습니다.는 '보다 낫다'를 한 것입니다.r윈, 린, 린, 둘둘 win win win win win win win win win win win win win win win win win win win win win win 。

import glob

mypath=r"C:\Users\dj\Desktop\nba"

files = glob.glob(mypath + r'\**\*.py', recursive=True)
# print(files) # as list
for f in files:
    print(f) # nice looking single line per file

주의: 깊이와 관계없이 모든 파일이 나열됩니다.

추가 라이트 라이브러리를 설치해도 괜찮다면 다음을 수행할 수 있습니다.

pip install plazy

사용방법:

import plazy

txt_filter = lambda x : True if x.endswith('.txt') else False
files = plazy.list_files(root='data', filter_func=txt_filter, is_include_root=True)

결과는 다음과 같습니다.

['data/a.txt', 'data/b.txt', 'data/sub_dir/c.txt']

Python 2.7과 Python 3 모두에서 작동합니다.

Github: https://github.com/kyzas/plazy#list-files

면책사항:나는 의 작가이다.plazy.

이 함수는 반복적으로 파일만 목록에 넣습니다.

import os


def ls_files(dir):
    files = list()
    for item in os.listdir(dir):
        abspath = os.path.join(dir, item)
        try:
            if os.path.isdir(abspath):
                files = files + ls_files(abspath)
            else:
                files.append(abspath)
        except FileNotFoundError as err:
            print('invalid directory\n', 'Error: ', err)
    return files

glob 모듈 내에서 "재귀적" 설정을 사용하여 하위 디렉토리를 검색할 수 있습니다.

예를 들어 다음과 같습니다.

import glob
glob.glob('//Mypath/folder/**/*',recursive = True)

두 번째 줄은 해당 폴더 위치의 하위 디렉터리 내의 모든 파일을 반환합니다(이 작업을 수행하려면 폴더 문자열 끝에 '**/*' 문자열이 필요합니다).

특히 하위 디렉토리 내의 텍스트파일을 찾고 싶은 경우 다음을 사용할 수 있습니다.

glob.glob('//Mypath/folder/**/*.txt',recursive = True)

가장 심플하고 기본적인 방법:

import os
for parent_path, _, filenames in os.walk('.'):
    for f in filenames:
        print(os.path.join(parent_path, f))

언급URL : https://stackoverflow.com/questions/18394147/how-to-do-a-recursive-sub-folder-search-and-return-files-in-a-list

반응형