이것은 내가 가지고 올 수있는 가장 빠른 해결책이 될 것으로 보인다이며 보다 빠른 os.walk
및 훨씬 빨리 어떤 것보다 glob
솔루션 .
- 또한 기본적으로 무료로 모든 중첩 된 하위 폴더 목록을 제공합니다.
- 여러 다른 확장을 검색 할 수 있습니다.
- 또한 변경하여 파일 중 하나를 전체 경로 또는 단지 이름을 반환하도록 선택할 수 있습니다
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"])
속도 분석
모든 하위 폴더와 기본 폴더 내에서 특정 파일 확장자를 가진 모든 파일을 가져 오는 다양한 방법
tl; dr :
- fast_scandir
분명히 승리하고 os.walk를 제외한 다른 모든 솔루션보다 두 배 빠릅니다.
- os.walk
조금 느리게 2 위입니다.
-사용 glob
하면 프로세스가 크게 느려집니다.
-어떤 결과도 자연 정렬을 사용하지 않습니다 . 즉, 결과가 다음과 같이 정렬됩니다 : 1, 10, 2. 자연스러운 정렬 (1, 2, 10)을 얻으려면 https://stackoverflow.com/a/48030307/2441026을 살펴보십시오.
결과 :
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
테스트는 W7x64, Python 3.8.1, 20 회 실행으로 수행되었습니다. 439 (부분적으로 중첩 된) 하위 폴더에 16596 개의 파일이 있습니다. https://stackoverflow.com/a/45646357/2441026
find_files
에서 왔으며 여러 확장을 검색 할 수 있습니다.
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)}")