Durch Verzeichnisse mit Python iterieren


157

Ich muss die Unterverzeichnisse eines bestimmten Verzeichnisses durchlaufen und nach Dateien suchen. Wenn ich eine Datei erhalte, muss ich sie öffnen, den Inhalt ändern und durch meine eigenen Zeilen ersetzen.

Ich habe es versucht:

import os

rootdir ='C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        f=open(file,'r')
        lines=f.readlines()
        f.close()
        f=open(file,'w')
        for line in lines:
            newline = "No you are not"
            f.write(newline)
        f.close()

aber ich bekomme einen Fehler. Was mache ich falsch?


12
"Ein Fehler" - insbesondere ein Fehler?
Daniel Roseman

1
Könnten Sie uns bitte ein wenig erklären, was Sie mit den Dateien / Verzeichnissen tun möchten, wenn Sie sie wie vorgesehen durchlaufen haben? Bitte geben Sie auch Fehlerdetails an.
ChrisProsser

1
Die Fehlermeldung, die ich bekomme, ist, dass die Datei cool.txt nicht gefunden wird. In meinem Testordner habe ich einen anderen Ordner namens src und im src-Ordner habe ich einen anderen Ordner namens main, in diesem Ordner habe ich cool.txt
Wolf

4
Kannst du einfach den Fehler in die Frage schreiben? Es ist mehr als ärgerlich und unnötig, die Kommentare durchlesen zu müssen, um sie zu finden.
Charlie Parker

1
über ein Jahr später kann ich nicht glauben, dass ich zurück bin und um die Veröffentlichung des Fehlers gebeten habe? @ Wolf
Charlie Parker

Antworten:


300

Der eigentliche Spaziergang durch die Verzeichnisse funktioniert so, wie Sie ihn codiert haben. Wenn Sie den Inhalt der inneren Schleife durch eine einfache printAnweisung ersetzen , können Sie sehen, dass jede Datei gefunden wird:

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print os.path.join(subdir, file)

Wenn beim Ausführen der oben genannten Schritte weiterhin Fehler auftreten, geben Sie bitte die Fehlermeldung ein.


Aktualisiert für Python3

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print(os.path.join(subdir, file))

1
C: / Benutzer / sid / Desktop / test \ src \ app / cool.txt C: / Benutzer / sid / Desktop / test \ src \ app / woohoo.txt Ja, in der offenen Anweisung meines Codes denke ich, ich muss Geben Sie den absoluten Pfad zur Datei an. import os rootdir = 'C: / Users / spemmara / Desktop / test / src / app /' für Unterverzeichnis, Verzeichnisse, Dateien in os.walk (rootdir): für Datei in Dateien: f = open (Unterverzeichnis + '/' + Datei , 'r') lines = f.readlines () f.close () f = open (Unterverzeichnis + '/' + file, 'w') für Zeile in Zeilen: newline = "hey i know" f.write (newline) f.close () Danke Mann. Es ist gelöst
Wolf

3
Hallo! Bitte beachten Sie, dass für "print" in Python 3 Klammern erforderlich sind, andernfalls wird ein Syntaxfehler zurückgegeben. Hoffe das hilft!
Tommaso Di Noto

14

Eine andere Möglichkeit, alle Dateien in Unterverzeichnissen zurückzugeben, ist die Verwendung despathlib in Python 3.4 eingeführten Moduls , das einen objektorientierten Ansatz für die Behandlung von Dateisystempfaden bietet (Pathlib ist auch in Python 2.7 über das Modul pathlib2 in PyPi verfügbar ):

from pathlib import Path

rootdir = Path('C:/Users/sid/Desktop/test')
# Return a list of regular files only, not directories
file_list = [f for f in rootdir.glob('**/*') if f.is_file()]

# For absolute paths instead of relative the current dir
file_list = [f for f in rootdir.resolve().glob('**/*') if f.is_file()]

Seit Python 3.5 unterstützt das globModul auch die rekursive Dateisuche:

import os
from glob import iglob

rootdir_glob = 'C:/Users/sid/Desktop/test/**/*' # Note the added asterisks
# This will return absolute paths
file_list = [f for f in iglob('**/*', recursive=True) if os.path.isfile(f)]

Die file_listbeiden oben genannten Ansätze können wiederholt werden, ohne dass eine verschachtelte Schleife erforderlich ist:

for f in file_list:
    print(f) # Replace with desired operations

1
Was ist hier für Python 3.6 vorzuziehen?
PhoenixDev

@PhoenixDev Ich habe noch nie gehört, dass ein Ansatz generell dem anderen empfohlen wird. Ich benutze pathlibmich lieber selbst, vor allem, weil mir die objektorientierte Methodensyntax gefällt. Es gibt andere Unterschiede, z. B. dass die Pfadbibliothek bestimmte Pfadklassen anstelle von Zeichenfolgen zurückgibt und die verfügbaren Funktionen zwischen den Bibliotheken unterschiedlich sind (z . B. os.path.expanduser('~')vs Path.home()). Durchsuchen Sie die Dokumentation und finden Sie heraus, welchen Ansatz Sie bevorzugen.
Joelostblom

Anstatt **das Glob-Muster hinzuzufügen , können Sie es verwenden rglob.
Georgy

12

Ab 2020 , glob.iglob(path/**, recursive=True)scheint die pythonic Lösung, das heißt:

import glob, os

for filename in glob.iglob('/pardadox-music/**', recursive=True):
    if os.path.isfile(filename): # filter dirs
        print(filename)

Ausgabe:

/pardadox-music/modules/her1.mod
/pardadox-music/modules/her2.mod
...

Anmerkungen:
1 - glob.iglob

glob.iglob(pathname, recursive=False)

Geben Sie einen Iterator zurück, der dieselben Werte liefert, glob()ohne sie alle gleichzeitig zu speichern.

2 - Wenn rekursiv ist True, stimmt das Muster '**'mit allen Dateien und null oder mehr directoriesund überein subdirectories.

3 - Wenn das Verzeichnis Dateien enthält, die mit beginnen, werden  .diese standardmäßig nicht abgeglichen. Betrachten Sie beispielsweise ein Verzeichnis mit  card.gif und .card.gif:

>>> import glob
>>> glob.glob('*.gif') ['card.gif'] 
>>> glob.glob('.c*')['.card.gif']

4 - Sie können auch verwenden rglob(pattern), was dem Aufrufen  glob() mit **/dem vor dem angegebenen relativen Muster hinzugefügten entspricht.


1
Diese Python- Lösung listet keine versteckten Dateien (auch als Dotfiles bezeichnet) auf, während die akzeptierte dies tut.
Ashrasmun

@ashrasmun Was Sie erwähnen, ist in docs.python.org/3/library/glob.html
CONvid19
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.