Verzeichnis liste ohne versteckte Verzeichnisse...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Stehe gerade auf den Schlauch... Ich möchte eine Liste aller Verzeichnisse und Unterverzeichnisse, aber ohne versteckte Verzeichnisse... Also alle Pfade die mit Punkt anfangen auslassen...

Mit os.walk() kommt man da nicht so schnell weiter...

Idee?

Rekursive Funktion mit os.listdir() ?

EDIT: Hm:

Code: Alles auswählen

import os, dircache

media_root = "./media"

def dir_walk(path):
    for name in dircache.listdir(path):
        if name.startswith("."):
            continue

        abs_path = os.path.join(path, name)
        if not os.path.isdir(abs_path):
            continue

        yield abs_path

        for dir in dir_walk(abs_path):
            yield dir


for i in dir_walk(media_root):
   print i
Was haltet ihr davon?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

import os

found = []
for root, dirs, files in os.walk('blub'):
    found.extend(d for d in dirs if not d.startswith('.'))

print found
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ne, ich brauche den vollen Pfad...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

import os

found = []
for root, dirs, files in os.walk('blub'):
    found.extend(os.path.join(root, d) for d in dirs if not d.startswith('.'))

print found 
Muss man dir denn alles vorkauen? :D
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Selbst mal ausprobiert? So einfach ist das nicht...

Sowas kommt raus:

Code: Alles auswählen

./media/PyLucid
./media/.svn/tmp
./media/.svn/props
./media/.svn/prop-base
./media/.svn/text-base
./media/.svn/tmp/props
./media/.svn/tmp/prop-base
./media/.svn/tmp/text-base
./media/PyLucid/tiny_mce
./media/PyLucid/internal_page
...
Das Verzeichnis ./media/.svn wird zwar ausgelassen, aber nicht die Unterverzeichnis darin ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

import os

found = []
for root, dirs, files in os.walk('blub'):
    for d in dirs:
        if d.startswith('.'):
            dirs.remove(d)
    found.extend(os.path.join(root, d) for d in dirs)

print found
Dann entfernt man die eben :D
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ne, ich glaube os.walk() ist hier nicht angebracht. Es ist langsamer, wenn auch nicht viel:

Code: Alles auswählen

import timeit, os

def dir_walk1(path):
    result = []
    for name in os.listdir(path):
        if name.startswith("."):
            continue

        abs_path = os.path.join(path, name)
        if not os.path.isdir(abs_path):
            continue

        result.append(abs_path)
        sub_dirs = dir_walk1(abs_path)
        if sub_dirs:
            result += sub_dirs

    return result

#_____________________________________________________________________________

def dir_walk2(path):
    found = []
    for root, dirs, files in os.walk(path):
        for d in dirs:
            if d.startswith('.'):
                dirs.remove(d)
        found.extend(os.path.join(root, d) for d in dirs)
    return found

#_____________________________________________________________________________

def dir_walk3(path):
    found = []
    for root, dirs, files in os.walk(path):
        for d in dirs:
            if d.startswith('.'):
                dirs.remove(d)
            else:
                found.append(os.path.join(root, d))

    return found

#_____________________________________________________________________________


loop = 20

tests = (
    ("dir_walk1('.')", "from __main__ import os, dir_walk1"),
    ("dir_walk2('.')", "from __main__ import os, dir_walk2"),
    ("dir_walk3('.')", "from __main__ import os, dir_walk3"),
)

for no, test in enumerate(tests):
    print "%s - %s" % (no+1, test[0])

    test = timeit.Timer(test[0], test[1])
    print "%.2f" % test.timeit(number=loop)

    print
Ausgabe:
1 - dir_walk1('.')
0.79

2 - dir_walk2('.')
1.06

3 - dir_walk3('.')
0.97
@audax: dir_walk2() ist deine Variante...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

achso, es geht um jeden Zyklus, das wusste ich nicht!

Ich dachte schon, es geht um Lesbarkeit und Wartbarkeit...wie bin ich blos darauf gekommen...
noob1
User
Beiträge: 9
Registriert: Mittwoch 9. Juli 2008, 09:24

in der eingesparten zeit könnte er die welt retten...
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Meine Variante kann man noch vereinfachen, denn ich if Abfrage kann man sich sparen.
externd ist wohl auch schneller als ein +=
Statt os.listdir nutzte ich auch eigentlich dircache.listdir, was nochmal ein tick schneller ist ;)

Ich nutzte dir_walk2():

Code: Alles auswählen

import timeit, os, dircache

def dir_walk1(path):
    result = []
    for name in os.listdir(path):
        if name.startswith("."):
            continue

        abs_path = os.path.join(path, name)
        if not os.path.isdir(abs_path):
            continue

        result.append(abs_path)
        result.extend(dir_walk1(abs_path))

    return result

#_____________________________________________________________________________

def dir_walk2(path):
    result = []
    for name in dircache.listdir(path):
        if name.startswith("."):
            continue

        abs_path = os.path.join(path, name)
        if not os.path.isdir(abs_path):
            continue

        result.append(abs_path)
        result.extend(dir_walk1(abs_path))

    return result

#_____________________________________________________________________________

def dir_walk3(path):
    found = []
    for root, dirs, files in os.walk(path):
        for d in dirs:
            if d.startswith('.'):
                dirs.remove(d)
            else:
                found.append(os.path.join(root, d))

    return found

#_____________________________________________________________________________


loop = 100

tests = (
    ("dir_walk1('.')", "from __main__ import os, dir_walk1"),
    ("dir_walk2('.')", "from __main__ import os, dircache, dir_walk2"),
    ("dir_walk3('.')", "from __main__ import os, dir_walk3"),
)

for no, test in enumerate(tests):
    print "%s - %s" % (no+1, test[0])

    test = timeit.Timer(test[0], test[1])
    print "%.2f" % test.timeit(number=loop)

    print
Ergebnis:

Code: Alles auswählen

1 - dir_walk1('.')
4.10

2 - dir_walk2('.')
3.75

3 - dir_walk3('.')
5.07
Finde jetzt nicht, das dir_walk2() wesentlich undurchsichtiger wäre als dir_walk3()...

Später kommt evtl. noch eine "skip-Liste" hinzu...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Naja, für mich fällt das unter "unnötige Mikrooptimierung".
BlackJack

Oh bitte Leute, ihr programmiert doch nicht erst seit gestern in Python: Aus einer Liste Elemente entfernen während man darüber iteriert ist eine doofe Idee. Also bitte die ``for``-Schleife durch so etwas hier ersetzen:

Code: Alles auswählen

dirs[:] = [d for d if d[0] != '.']
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

uhm...da war ja was...
BlackJack

@jens: Vielleicht ist die `os.walk()` Lösung ja auch deswegen geringfügig langsamer, weil bei aufeinander folgenden versteckten Verzeichnissen jedes zweite doch im Ergebnis landet, wenn man ``for`` und `remove()` verwendet.
Antworten