Wie verwendet man glob(), um Dateien rekursiv zu finden?

Lesezeit: 5 Minuten

Benutzer-Avatar
Ben Gartner

Das habe ich:

glob(os.path.join('src','*.c'))

aber ich möchte die Unterordner von src durchsuchen. So etwas würde funktionieren:

glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))

Aber das ist offensichtlich begrenzt und klobig.

  • nicht glob('src/**/*.c') Arbeit in diesem Fall?

    – Likith Reddy

    13. September 2021 um 8:06 Uhr

Benutzer-Avatar
Johann Dahlin

pathlib.Pfad.rglob

Verwenden pathlib.Path.rglob von der pathlib Modul, das in Python 3.5 eingeführt wurde.

from pathlib import Path

for path in Path('src').rglob('*.c'):
    print(path.name)

Wenn Sie pathlib nicht verwenden möchten, können Sie verwenden glob.glob('**/*.c')aber vergessen Sie nicht, die zu übergeben recursive Schlüsselwortparameter und es wird übermäßig viel Zeit für große Verzeichnisse benötigen.

Für Fälle, in denen übereinstimmende Dateien beginnend mit einem Punkt (.); wie Dateien im aktuellen Verzeichnis oder versteckte Dateien auf Unix-basierten Systemen verwenden Sie die os.walk Lösung unten.

os.walk

Verwenden Sie für ältere Python-Versionen os.walk rekursiv durch ein Verzeichnis gehen und fnmatch.filter mit einem einfachen Ausdruck vergleichen:

import fnmatch
import os

matches = []
for root, dirnames, filenames in os.walk('src'):
    for filename in fnmatch.filter(filenames, '*.c'):
        matches.append(os.path.join(root, filename))

  • Für Python älter als 2.2 gibt es os.path.walk() was etwas umständlicher zu bedienen ist als os.walk()

    – John LaRooy

    2. Februar 2010 um 19:34 Uhr

  • @gnibbler Ich weiß, das ist ein alter Kommentar, aber mein Kommentar soll die Leute das wissen lassen os.path.walk() ist veraltet und wurde in Python 3 entfernt.

    – Pedro Cunha

    18. Januar 2013 um 16:14 Uhr

  • @DevC das könnte in dem in dieser Frage gestellten speziellen Fall funktionieren, aber es ist leicht vorstellbar, dass jemand es mit Abfragen wie ‘a*.c’ usw. verwenden möchte, daher denke ich, dass es sich lohnt, die aktuelle etwas langsame Antwort beizubehalten.

    – Johan Dahlin

    19. Mai 2014 um 19:29 Uhr

  • Für das, was es wert ist, war in meinem Fall das Finden von über 10.000 Dateien mit glob viel langsamer als mit os.walk, also habe ich mich aus diesem Grund für die letztere Lösung entschieden.

    – Gottschmied

    12. September 2018 um 6:23 Uhr

  • Für Python 3.4, pathlib.Path('src').glob('**/*.c') sollte arbeiten.

    – CivFan

    11. April 2019 um 0:16 Uhr

Benutzer-Avatar
Pedro Lobito

Für Python >= 3.5 Sie können verwenden **, recursive=True :

import glob
for f in glob.glob('/path/**/*.c', recursive=True):
    print(f)

Wenn rekursiv ist Truedas Muster ** stimmt mit allen Dateien und null oder mehr überein directories und subdirectories. Wenn auf das Muster ein folgt os.sepnur Verzeichnisse und subdirectories passen.


Python 3.6-Demo

  • Das funktioniert besser als pathlib.Path(‘./path/’).glob(‘*/‘), weil es auch so im Ordner mit der Größe 0 ist

    – Karl Walker

    18. April 2020 um 15:14 Uhr

  • In Python 3.9.1 ist recursive standardmäßig auf False gesetzt.

    – PYB

    30. Dezember 2020 um 21:53 Uhr

  • recursive ist auch eingestellt False standardmäßig in Python 3.8.*.

    – rayryeng

    25. Oktober 2021 um 14:01 Uhr

Benutzer-Avatar
Bruno Oliveira

Ähnlich wie bei anderen Lösungen, aber mit fnmatch.fnmatch anstelle von glob, da os.walk die Dateinamen bereits aufgelistet hat:

import os, fnmatch


def find_files(directory, pattern):
    for root, dirs, files in os.walk(directory):
        for basename in files:
            if fnmatch.fnmatch(basename, pattern):
                filename = os.path.join(root, basename)
                yield filename


for filename in find_files('src', '*.c'):
    print 'Found C source:', filename

Außerdem ermöglicht Ihnen die Verwendung eines Generators, jede Datei so zu verarbeiten, wie sie gefunden wird, anstatt alle Dateien zu finden und dann sie verarbeiten.

Benutzer-Avatar
Wunder2k

Ich habe das Glob-Modul so modifiziert, dass es ** für rekursives Globbing unterstützt, z.

>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')

https://github.com/miracle2k/python-glob2/

Nützlich, wenn Sie Ihren Benutzern die Möglichkeit geben möchten, die **-Syntax zu verwenden, und daher os.walk() allein nicht gut genug ist.

Benutzer-Avatar
taleinat

Ab Python 3.4 kann man die verwenden glob() Methode eines der Path Klassen im Neuen pathlib Modul, das unterstützt ** Platzhalter. Zum Beispiel:

from pathlib import Path

for file_path in Path('src').glob('**/*.c'):
    print(file_path) # do whatever you need with these files

Aktualisieren:
Ab Python 3.5 wird dieselbe Syntax auch von unterstützt glob.glob().

Benutzer-Avatar
Sebastian Mach

import os
import fnmatch


def recursive_glob(treeroot, pattern):
    results = []
    for base, dirs, files in os.walk(treeroot):
        goodfiles = fnmatch.filter(files, pattern)
        results.extend(os.path.join(base, f) for f in goodfiles)
    return results

fnmatch gibt Ihnen genau die gleichen Muster wie globalso ist dies wirklich ein ausgezeichneter Ersatz für glob.glob mit sehr enger Semantik. Eine iterative Version (zB ein Generator), IOW ein Ersatz für glob.iglobist eine triviale Anpassung (just yield die Zwischenergebnisse, wie Sie gehen, statt extendeine einzelne Ergebnisliste zur Rückgabe am Ende).

Benutzer-Avatar
Geoff Reedy

Sie möchten verwenden os.walk um Dateinamen zu sammeln, die Ihren Kriterien entsprechen. Zum Beispiel:

import os
cfiles = []
for root, dirs, files in os.walk('src'):
  for file in files:
    if file.endswith('.c'):
      cfiles.append(os.path.join(root, file))

1143780cookie-checkWie verwendet man glob(), um Dateien rekursiv zu finden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy