Dies scheint die schnellste Lösung zu sein, die ich finden konnte, und sie ist schneller als os.walk
und viel schneller als jede glob
andere Lösung .
- Außerdem erhalten Sie kostenlos eine Liste aller verschachtelten Unterordner.
- Sie können nach verschiedenen Erweiterungen suchen.
- Sie können auch durch Änderung entweder vollständige Pfade oder einfach nur die Namen für die Dateien zurückzukehren wählen
f.path
zu f.name
(nicht ändern , es für Unterordner!).
Argumente : dir: str, ext: list
.
Die Funktion gibt zwei Listen zurück : subfolders, files
.
Unten finden Sie eine detaillierte Geschwindigkeitsanalyse.
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"])
Geschwindigkeitsanalyse
für verschiedene Methoden, um alle Dateien mit einer bestimmten Dateierweiterung in allen Unterordnern und im Hauptordner abzurufen.
tl; dr:
- fast_scandir
gewinnt eindeutig und ist doppelt so schnell wie alle anderen Lösungen außer os.walk.
- os.walk
ist der zweite Platz etwas langsamer.
- Die Verwendung glob
verlangsamt den Prozess erheblich.
- Keines der Ergebnisse verwendet eine natürliche Sortierung . Dies bedeutet, dass die Ergebnisse wie folgt sortiert werden: 1, 10, 2. Um eine natürliche Sortierung (1, 2, 10) zu erhalten, besuchen Sie bitte https://stackoverflow.com/a/48030307/2441026
Ergebnisse:
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
Die Tests wurden mit W7x64, Python 3.8.1, 20 Läufen durchgeführt. 16596 Dateien in 439 (teilweise verschachtelten) Unterordnern.
find_files
stammt von https://stackoverflow.com/a/45646357/2441026 und ermöglicht die Suche nach mehreren Erweiterungen.
fast_scandir
wurde von mir geschrieben und wird auch eine Liste von Unterordnern zurückgeben. Sie können ihm eine Liste mit Erweiterungen geben, nach denen gesucht werden soll (ich habe eine Liste mit einem Eintrag zu einem einfachen getestet if ... == ".jpg"
und es gab keinen signifikanten Unterschied).
# -*- 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)}")