Verzeichnisbaumliste in Python

Antworten:

615

Dies ist eine Möglichkeit, jede Datei und jedes Verzeichnis in einem Verzeichnisbaum zu durchlaufen:

import os

for dirname, dirnames, filenames in os.walk('.'):
    # print path to all subdirectories first.
    for subdirname in dirnames:
        print(os.path.join(dirname, subdirname))

    # print path to all filenames.
    for filename in filenames:
        print(os.path.join(dirname, filename))

    # Advanced usage:
    # editing the 'dirnames' list will stop os.walk() from recursing into there.
    if '.git' in dirnames:
        # don't go into any .git directories.
        dirnames.remove('.git')
Jerub
quelle
19
Wenn Sie diesen Code (wie er ist) über die Python-Shell ausführen, denken Sie daran, dass Strg + C die Ausgabe an diese Shell anhält. ;)
Gary
41
Dies wird rekursiv Dateien und Verzeichnisse
auflisten
Sie können die Verzeichnisnamenliste sogar bearbeiten, um zu verhindern, dass sie einige Pfade zurückkehrt.
Bugloaf
8
@ Clément "Wenn topdown True ist, kann der Aufrufer die Liste der Verzeichnisnamen direkt ändern (möglicherweise mithilfe der Del- oder Slice-Zuweisung), und walk () wird nur in die Unterverzeichnisse zurückgeführt, deren Namen in Verzeichnisnamen verbleiben. Dies kann zum Bereinigen der Liste verwendet werden suchen, eine bestimmte Besuchsreihenfolge festlegen oder walk () sogar über Verzeichnisse informieren, die der Anrufer erstellt oder umbenennt, bevor er walk () wieder aufnimmt. " von docs.python.org/2/library/os.html#os.walk
Bugloaf
Der einfachere Weg, einige Verzeichnisse zu ignorieren, besteht darin, sie erst gar nicht zu Dirnamen hinzuzufügenfor subdirname in dirnames: if subdirname != '.git'
smci
537

Sie können verwenden

os.listdir(path)

Als Referenz und weitere Betriebssystemfunktionen finden Sie hier:

rslite
quelle
1
Nun, die ursprüngliche Frage ist nur vage genug, um nicht zu wissen, ob sie eine rekursive Lösung wollten. "Alle Dateien in einem Verzeichnis" könnte als rekursiv interpretiert werden.
Tommy
3
@Tommy, ein "Verzeichnis" ist eine klar definierte Datenstruktur und bezieht sich eher auf "ls" als auf "ls -R". Außerdem funktionieren fast alle UNIX-Tools standardmäßig nicht rekursiv. Ich weiß nicht, was der Fragesteller meinte, aber was er schrieb, war klar.
Torsten Bronger
In den Python 3-Dokumenten wird os.scandirjedoch empfohlen, stattdessen zu verwenden , da Sie in vielen Fällen Systemaufrufe verhindern und eine kostenlose Beschleunigung erzielen können (sowohl IPC als auch E / A sind langsam).
Jappie Kerk
5
listdir gibt Ihnen nur den Dateinamen im Verzeichnis an. Gibt es eine Methode, um den vollständigen Pfad abzurufen?
Greperror
1
@greperror Sie können os.path.abspath verwenden , um den vollständigen Pfad abzurufen . Verwenden Sie außerdem die Datei os.path.isfile oder , um zu überprüfen, ob ein bestimmter Pfad eine Datei ist os.path.isdir.
Aleksandar
111

Hier ist eine Hilfsfunktion, die ich ziemlich oft benutze:

import os

def listdir_fullpath(d):
    return [os.path.join(d, f) for f in os.listdir(d)]
vergoldet
quelle
3
Ein Generator wäre besser.
Robert Siemer
1
@ RobertSiemer das hängt von der Nutzung ab. In vielen Fällen wäre eine Liste besser, aber ich denke, ein Generator ist vielseitiger, da er in eine Liste konvertiert werden kann. Es hängt davon ab, ob Sie nach Vielseitigkeit oder etwas Schlankerem suchen.
James Mchugh
3
Es ist zehn Jahre her, aber ich glaube, ich habe es so gemacht, weil os.listdir () eine Liste zurückgibt und ich das nachgeahmt habe.
Golday
82
import os

for filename in os.listdir("C:\\temp"):
    print  filename
Curtisk
quelle
16
r'C:\temp'ist klarer und "C:\\temp"Rawstrings vorzuziehen sind Backslashes vorzuziehen.
smci
13

Wenn Sie Globbing-Fähigkeiten benötigen, gibt es auch dafür ein Modul. Zum Beispiel:

import glob
glob.glob('./[0-9].*')

wird etwas zurückgeben wie:

['./1.gif', './2.txt']

Siehe die Dokumentation hier .

kenny
quelle
10

Versuche dies:

import os
for top, dirs, files in os.walk('./'):
    for nm in files:       
        print os.path.join(top, nm)
paxdiablo
quelle
In einer Zeile: [top + os.sep + f für top, dirs, Dateien in os.walk ('./') für f in Dateien]
J. Peterson
9

Für Dateien im aktuellen Arbeitsverzeichnis ohne Angabe eines Pfads

Python 2.7:

import os
os.listdir(os.getcwd())

Python 3.x:

import os
os.listdir()

Vielen Dank an Stam Kaly für den Kommentar zu Python 3.x.

Dave Ingenieur
quelle
5
os.listdir()listet standardmäßig Elemente im aktuellen Verzeichnis auf! Also keine Notwendigkeit für os.getcwd():)
Stam Kaly
Wie würde ich das machen? Wenn ich >>> os.listdir () ohne Argument verwende, erhalte ich: TypeError: listdir () nimmt genau 1 Argument (0 angegeben)
Dave Engineer
2
Ich nehme an, Sie laufen auf 2.7. Dies wurde am 3.x
Stam Kaly
5

Eine rekursive Implementierung

import os

def scan_dir(dir):
    for name in os.listdir(dir):
        path = os.path.join(dir, name)
        if os.path.isfile(path):
            print path
        else:
            scan_dir(path)
Arnaldo P. Figueira Figueira
quelle
3

Ich habe eine lange Version mit allen Optionen geschrieben, die ich möglicherweise benötige: http://sam.nipl.net/code/python/find.py

Ich denke, es wird auch hier passen:

#!/usr/bin/env python

import os
import sys

def ls(dir, hidden=False, relative=True):
    nodes = []
    for nm in os.listdir(dir):
        if not hidden and nm.startswith('.'):
            continue
        if not relative:
            nm = os.path.join(dir, nm)
        nodes.append(nm)
    nodes.sort()
    return nodes

def find(root, files=True, dirs=False, hidden=False, relative=True, topdown=True):
    root = os.path.join(root, '')  # add slash if not there
    for parent, ldirs, lfiles in os.walk(root, topdown=topdown):
        if relative:
            parent = parent[len(root):]
        if dirs and parent:
            yield os.path.join(parent, '')
        if not hidden:
            lfiles   = [nm for nm in lfiles if not nm.startswith('.')]
            ldirs[:] = [nm for nm in ldirs  if not nm.startswith('.')]  # in place
        if files:
            lfiles.sort()
            for nm in lfiles:
                nm = os.path.join(parent, nm)
                yield nm

def test(root):
    print "* directory listing, with hidden files:"
    print ls(root, hidden=True)
    print
    print "* recursive listing, with dirs, but no hidden files:"
    for f in find(root, dirs=True):
        print f
    print

if __name__ == "__main__":
    test(*sys.argv[1:])
Sam Watkins
quelle
3

Hier ist eine weitere Option.

os.scandir(path='.')

Es gibt einen Iterator von os.DirEntry-Objekten zurück, die den Einträgen (zusammen mit Dateiattributinformationen) in dem durch path angegebenen Verzeichnis entsprechen.

Beispiel:

with os.scandir(path) as it:
    for entry in it:
        if not entry.name.startswith('.'):
            print(entry.name)

Die Verwendung von scandir () anstelle von listdir () kann die Leistung von Code erheblich verbessern, der auch Dateityp- oder Dateiattributinformationen benötigt , da os.DirEntry-Objekte diese Informationen verfügbar machen, wenn das Betriebssystem sie beim Scannen eines Verzeichnisses bereitstellt. Alle os.DirEntry-Methoden können einen Systemaufruf ausführen, aber is_dir () und is_file () erfordern normalerweise nur einen Systemaufruf für symbolische Links. os.DirEntry.stat () erfordert unter Unix immer einen Systemaufruf, unter Windows jedoch nur einen für symbolische Links.

Python-Dokumente

Khaino
quelle
3

Während das os.listdir()Erstellen einer Liste von Datei- und Verzeichnisnamen in Ordnung ist, möchten Sie häufig mehr tun, sobald Sie diese Namen haben - und in Python3 vereinfacht pathlib diese anderen Aufgaben. Lassen Sie uns einen Blick darauf werfen und sehen, ob es Ihnen genauso gut gefällt wie mir.

Um Verzeichnisinhalte aufzulisten, erstellen Sie ein Pfadobjekt und greifen Sie auf den Iterator zu:

In [16]: Path('/etc').iterdir()
Out[16]: <generator object Path.iterdir at 0x110853fc0>

Wenn wir nur eine Liste von Namen von Dingen wollen:

In [17]: [x.name for x in Path('/etc').iterdir()]
Out[17]:
['emond.d',
 'ntp-restrict.conf',
 'periodic',

Wenn Sie nur die dirs wollen:

In [18]: [x.name for x in Path('/etc').iterdir() if x.is_dir()]
Out[18]:
['emond.d',
 'periodic',
 'mach_init.d',

Wenn Sie die Namen aller conf-Dateien in diesem Baum möchten:

In [20]: [x.name for x in Path('/etc').glob('**/*.conf')]
Out[20]:
['ntp-restrict.conf',
 'dnsextd.conf',
 'syslog.conf',

Wenn Sie eine Liste von conf-Dateien im Baum> = 1K möchten:

In [23]: [x.name for x in Path('/etc').glob('**/*.conf') if x.stat().st_size > 1024]
Out[23]:
['dnsextd.conf',
 'pf.conf',
 'autofs.conf',

Das Auflösen relativer Pfade wird einfach:

In [32]: Path('../Operational Metrics.md').resolve()
Out[32]: PosixPath('/Users/starver/code/xxxx/Operational Metrics.md')

Das Navigieren mit einem Pfad ist ziemlich klar (obwohl unerwartet):

In [10]: p = Path('.')

In [11]: core = p / 'web' / 'core'

In [13]: [x for x in core.iterdir() if x.is_file()]
Out[13]:
[PosixPath('web/core/metrics.py'),
 PosixPath('web/core/services.py'),
 PosixPath('web/core/querysets.py'),
Steve Tarver
quelle
1

Ein netter Einzeiler, um nur die Dateien rekursiv aufzulisten. Ich habe dies in meiner Anweisung setup.py package_data verwendet:

import os

[os.path.join(x[0],y) for x in os.walk('<some_directory>') for y in x[2]]

Ich weiß, dass es nicht die Antwort auf die Frage ist, aber es kann nützlich sein

fivetentaylor
quelle
1

Für Python 2

#!/bin/python2

import os

def scan_dir(path):
    print map(os.path.abspath, os.listdir(pwd))

Für Python 3

Für Filter und Karte müssen Sie sie mit list () umschließen

#!/bin/python3

import os

def scan_dir(path):
    print(list(map(os.path.abspath, os.listdir(pwd))))

Die Empfehlung lautet nun, dass Sie Ihre Verwendung von Map und Filter durch Generatorausdrücke oder Listenverständnisse ersetzen:

#!/bin/python

import os

def scan_dir(path):
    print([os.path.abspath(f) for f in os.listdir(path)])
Alejandro Blasco
quelle
1

Hier ist eine einzeilige pythonische Version:

import os
dir = 'given_directory_name'
filenames = [os.path.join(os.path.dirname(os.path.abspath(__file__)),dir,i) for i in os.listdir(dir)]

Dieser Code listet den vollständigen Pfad aller Dateien und Verzeichnisse im angegebenen Verzeichnisnamen auf.

salehinejad
quelle
Vielen Dank, Saleh, aber Ihr Code hat nicht vollständig funktioniert, und der Code wurde wie folgt geändert: 'dir =' angegebener_Verzeichnisname 'Dateinamen = [os.path.abspath (os.path.join (dir, i)) für i in os.listdir (dir)] '
HassanSh__3571619
1

Ich weiß, das ist eine alte Frage. Dies ist eine nette Art und Weise, wie ich auf eine Liunx-Maschine gestoßen bin.

import subprocess
print(subprocess.check_output(["ls", "/"]).decode("utf8"))
apeter
quelle
0
#import modules
import os

_CURRENT_DIR = '.'


def rec_tree_traverse(curr_dir, indent):
    "recurcive function to traverse the directory"
    #print "[traverse_tree]"

    try :
        dfList = [os.path.join(curr_dir, f_or_d) for f_or_d in os.listdir(curr_dir)]
    except:
        print "wrong path name/directory name"
        return

    for file_or_dir in dfList:

        if os.path.isdir(file_or_dir):
            #print "dir  : ",
            print indent, file_or_dir,"\\"
            rec_tree_traverse(file_or_dir, indent*2)

        if os.path.isfile(file_or_dir):
            #print "file : ",
            print indent, file_or_dir

    #end if for loop
#end of traverse_tree()

def main():

    base_dir = _CURRENT_DIR

    rec_tree_traverse(base_dir," ")

    raw_input("enter any key to exit....")
#end of main()


if __name__ == '__main__':
    main()
Alok
quelle
5
Diese Frage hat bereits eine vollkommen gute Antwort, es besteht keine Notwendigkeit, sie erneut zu beantworten
Mike Pennington
0

Zu Ihrer Information Fügen Sie einen Filter für den Import von Erweiterungs- oder Ext-Dateiimporten hinzu

path = '.'
for dirname, dirnames, filenames in os.walk(path):
    # print path to all filenames with extension py.
    for filename in filenames:
        fname_path = os.path.join(dirname, filename)
        fext = os.path.splitext(fname_path)[1]
        if fext == '.py':
            print fname_path
        else:
            continue
moylop260
quelle
0

Wenn ich das mir vorstellen würde, würde ich das einwerfen. Einfache und schmutzige Art, Wildcard-Suchen durchzuführen.

import re
import os

[a for a in os.listdir(".") if re.search("^.*\.py$",a)]
bng44270
quelle
0

Der folgende Code listet Verzeichnisse und die Dateien im Verzeichnis auf

def print_directory_contents(sPath):
        import os                                       
        for sChild in os.listdir(sPath):                
            sChildPath = os.path.join(sPath,sChild)
            if os.path.isdir(sChildPath):
                print_directory_contents(sChildPath)
            else:
                print(sChildPath)
Heenashree Khandelwal
quelle
0

Die, die mit mir gearbeitet hat, ist eine Art modifizierte Version von Salehs Antwort oben.

Der Code lautet wie folgt:

"dir = 'angegebener_Verzeichnisname' Dateinamen = [os.path.abspath (os.path.join (dir, i)) für i in os.listdir (dir)]"

HassanSh__3571619
quelle