Seite 1 von 2
Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Montag 4. Januar 2016, 02:45
von DMD-OL
hallo
ich möchte gern nach nur nach einem einzigen bestimmten Ordner auf Festplatte C:\ suchen, wobei ich mir dann
gerne die pfadangabe nur bis zum gesuchten ordner ausgeben lassen würde, sobald der ordner einmal gefunden wurde...
soll heißen, wenn ich Python27 suche (egal wo der auf der festplatte ist) hätte ich gern beispielsweise:
C:\Users\Python27 oder
C:\Window\Brechstange\Python27
ich bekomm das nur für ordner direkt auf C:\ hin und auch leider ohne pfadangabe

erste versuche bringen mich auf dies:
Code: Alles auswählen
import os
os.chdir(r'\ ')
#rootDir = 'Python27'
rootDir = 'Users'
#rootDir = 'Windows'
counter = 0
for dirName, subdirList, fileList in os.walk(rootDir):
if counter == 0:
print dirName
print subdirList
print fileList
counter += 1
else:
break
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Montag 4. Januar 2016, 10:23
von Sirius3
@DMD-OL: vergiss erst mal, dass es chdir gibt. Arbeite statt dessen mit absoluten Pfaden. Wo suchst Du etwas? Dein rootDir ist ja wohl 'C:\' weil das der Startpunkt Deiner Suche ist. Was bei Dir rootDir heißt sollte also searching_for heißen.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Montag 4. Januar 2016, 12:32
von BlackJack
@DMD-OL: Der `counter` macht keinen Sinn weil die Schleife durch diese Logik grundsätzlich gleich beim ersten Durchlauf abgebrochen wird. Da macht also nicht nur `counter` keinen Sinn, sondern auch die Schleife ist überflüssig. Der Code ist im Grunde nahezu äquivalent zu dem hier:
Code: Alles auswählen
import os
dir_name, sub_directories, filenames = next(os.walk('C:/Users'))
print dir_name
print sub_directories
print filenames
Als erstes solltest Du das in eine Funktion verpacken und nicht auf Modulebene schreiben. Dann kann die Schleife durch ein ``return`` abgebrochen werden welches das gewünschte Ergebnis an den Aufrufer zurück gibt.
Dann musst Du die Schleife solange durchlaufen bis tatsächlich die gewünschte Information gefunden wurde. Darauf musst Du *testen*.
Vielleicht hilft es wenn Du einfach mal die Schleife über eine kleinere Verzeichnishierarchie laufen lässt, statt dem kompletten Laufwerk C:, und Dir anschaust an was für Werte die drei Namen in jedem Schleifendurchlauf gebunden werden. Dann sollte klar werden wie der Test aussehen muss.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Mittwoch 6. Januar 2016, 09:23
von kodela
Ich denke, die gewünschte Ordnersuche könnte man so umsetzen:
Code: Alles auswählen
#!/usr/bin/env python35
import os
def seek_Dir(root_dir, seek_dir):
os.chdir(r'\ ')
for dirname, subdirlist, filelist in os.walk(root_dir):
if seek_dir in dirname:
return dirname, subdirlist, filelist
def main():
root_dir = 'C:'
dir_name, subdir_list, file_list = seek_Dir(root_dir, 'VideoLAN\\VLC')
print(dir_name)
print(subdir_list)
print(file_list)
if __name__ == "__main__":
main()
Könnte man mit seek_Dir() auch den ganzen Computer nach einem Ordner durchsuchen und wenn ja, wie. Unter Windows gibt der Explorer dafür "Computer" als Adresse aus. "Computer" wird aber als Rootverzeichnis nicht akzeptiert.
Ich finde die Dokumentation zu os.chdir() nicht und weiß auch die Bedeutung von "r" vor '\' nicht und kann nur vermuten, dass damit das absolute Rootverzeichnis gemeint ist. Ich schwimme hier also.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Mittwoch 6. Januar 2016, 09:39
von Sirius3
@kodela: lösch das "os.chdir" raus. Das macht doch gar keinen Sinn und schadet nur. Deine Suche ist zu simple. Es würde auch ein Verzeichnis mit den Namen "C:\xyVideoLAN\VLCdu" finden.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Mittwoch 6. Januar 2016, 10:34
von /me
Die Idee des Codes ist grundsätzlich in Ordnung. Korrekt sähe es allerdings so aus:
Code: Alles auswählen
import os
def get_folders(base_dir, search_name):
for dir_name, sub_directories, filenames in os.walk(base_dir):
if search_name in sub_directories:
return os.path.join(dir_name, search_name)
Dann würde ich auch noch das `return` durch ein `yield` ersetzen um die Funktion universaler zu machen. Damit hast du dann die Chance über alle gefundenen Verzeichnisse zu iterieren oder alternativ einfach mit `next` das erste gefundene Verzeichnis zu holen.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Mittwoch 6. Januar 2016, 23:09
von kodela
@BlackJack: Ja, da habe ich zu kurz gedacht. Mit meinem Code wird der gesuchte Pfad nicht eindeutig gefunden.
@/me: Da die Suche mit meinem Code nicht korrekt war, habe ich den Vorschlag von Dir übernommen. Alles zusammen sieht damit so aus:
Code: Alles auswählen
#!/usr/bin/env python35
import os
def get_folders(base_dir, search_name):
for dir_name, sub_directories, filenames in os.walk(base_dir):
if search_name in sub_directories:
return os.path.join(dir_name)
def main():
root_dir = 'C:\\'
seek_dir = 'VLC'
dir_name = get_folders(root_dir, 'VLC')
print(dir_name + '\\' + seek_dir + '\\')
if __name__ == "__main__":
main()
"""
Ausgabe:
C:\Program Files (x86)\VideoLAN\VLC\
Process finished with exit code 0
"""
Allerdings ist es damit nicht möglich, ein Verzeichnis mit einem bestimmten Unterverzeichnis zu suchen. Das muss aber nicht sein, wenn man das Unterverzeichnis sucht und damit den kompletten Pfad bildet. Mit anderen Worten, ich suchte vorher nach "VideoLAN\VLC" und fand "C:\Program Files (x86)\VideoLAN\VLC". Jetzt suche ich nach "VLC" und finde, wenn ich Glück habe, als erstes "C:\Program Files (x86)\VideoLAN" und kann mir daraus auch "C:\Program Files (x86)\VideoLAN\VLC" bilden, den gesuchten Installationsordner für den VLC media player.
Allerdings kann es sein, dass ich als erstes einen ganz anderen Pfad finde, zum Beispiel "C:\Mediaobjekte\VLC". Ich muss also eine weitere Suche anschließen, die nach "vlc.exe" oder sonst einer Datei, die in dem gesuchten Verzeichnis vertreten sein muss. Das wäre zwar bei meinem ersten Code ebenfalls angebracht, aber die Wahrscheinlichkeit, dass es ein Verzeichnis "C:\Program Files (x86)\VideoLAN\VLC" gibt, das nicht das Installationsverzeichnis für den VLC ist, geht gegen Null.
Für eine weitere Suche hast Du die Verwendung von `yield`an Stelle von 'return' vorgeschlagen. Wenn ich es richtig sehe, kann man damit eine rekursive Suche konstruieren. Das ist mir aber bislang noch nicht gelungen. Versucht habe ich den Aufruf über eine Endlosschleife. Kannst Du eine Beschreibung der Generatorfunktion empfehlen? Schön wäre eine deutsche.
Bei meinem letzten nicht funktionierender Versuch sieht der Aufruf so aus:
Code: Alles auswählen
def main():
root_dir = 'D:\\'
seek_dir = 'VLC'
dir_name = get_folders(root_dir, 'VLC')
while True:
print(dir_name + '\\' + seek_dir + '\\')
# hier auf richtiges Verzeichnis prüfen und gegebenenfals abbrechen
dir_name = next(get_folders)
Natürlich ist in get_folders() das "return" durch "yield" ersetzt.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 00:10
von BlackJack
@kodela: `dir_name` ist kein Verzeichnisname sondern der Generator. *Den* kann man mit `next()` benutzen wenn man das nächste Ergebnis haben möchte, aber wenn man das in einer Schleife macht dann sollte man besser direkt mit ``for`` über die Ergebnisse iterieren statt ``while True:`` und `next()` zu verwenden. Dann müsste man ja auch noch ein ``try``/``except`` für die `StopIteration`-Ausnahme dazu schreiben. Das wäre im Gegensatz zu einer ``for``-Schleife ziemlich umständlich.
Generatorfunktionen haben nicht zwingend mit Rekursion zu tun. Man kann eine rekursive Generatorfunktion schreiben, muss es aber nicht. In diesem Fall wird ja `os.walk()` verwendet, also ist keine Rekursion in der eigenen Funktion nötig.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 00:27
von kodela
@BlackJack: Wie kann ich dann diese Anzeige bei einem Breakpoint in der Zeile von main() mit dem "print()" verstehen?
Code: Alles auswählen
dir_name = {str} 'C:\\Program Files (x86)\\VideoLAN'
root_dir = {str} 'C:\\'
seek_dir = {str} 'VLC'
PS:
Aha, diese obige Anzeige habe ich nur bei einem "return". Mit "yield" bekomme ich folgende Fehlermeldung:
Code: Alles auswählen
File "I:/Python/PyCharm/Textmenues/test.py", line 17, in main
print(dir_name + '\\' + seek_dir + '\\')
TypeError: unsupported operand type(s) for +: 'generator' and 'str'
Da geht mir jetzt ein Licht auf. Danke für Deinen Hinweis.
Und die Anzeige beim Debuggen sieht nun so aus:
Code: Alles auswählen
dir_name = {generator} <generator object get_folders at 0x02EDB900>
root_dir = {str} 'C:\\'
seek_dir = {str} 'VLC'
Wie komme ich jetzt aber zu dem gesuchten Pfad-Bezeichner?
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 00:35
von BlackJack
@kodela: Gar nicht. Dann hast Du da kein ``yield`` statt ``return`` stehen. Eine Generatorfunktion liefert beim Aufruf ein Generatorobjekt, sonst ist es keine Generatorfunktion.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 00:43
von kodela
@BlackJack: Doch, das hatte ich schon, deshalb kam ja die Fehlermeldung, weil mit "yield" der Rückgabewert nicht mehr als String behandelt werden konnte. Siehe auch meine PS-Anmerkung.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 01:01
von BlackJack
@kodela: Die Pfade bekommst Du vom Generatorobjekt. Zum Beispiel über eine ``for``-Schleife über das Objekt oder in dem Du `next()` damit aufrufst. Je nach dem ob man über alle iterieren möchte oder eben nur gezielt einen/den ersten Pfad haben möchte.
Die Dokumentation zu Generatorfunktionen bzw. dem ``yield``-Schlüsselwort sollte irgendwo den Link zum entsprechenden PEP enthalten wo das ganze etwas ausführlicher beschrieben wird. Allerdings auf Englisch. „
It's english, get over it”.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 01:15
von sepplx123
Wenn man nicht nur auf einer Festplatte sondern auf allen suchen möchte, so habe ich folgendes gefunden:
https://pypi.python.org/pypi/psutil
Das könnte auch noch hilfreich sein:
http://stackoverflow.com/questions/3596 ... ws-and-mac
Disks
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
>>>
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
>>>
>>> psutil.disk_io_counters(perdisk=False)
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568)
>>>
Mal kurz in der shell getestet (bei windows):
Code: Alles auswählen
import psutil
for element in psutil.disk_partitions():
print element.device
C:\
D:\
E:\
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 08:04
von Sirius3
@kodela: normalerweise sucht man ja nach Programmen nur in den Standardpfaden und nicht auf der ganzen Festplatte. Sollte ein Nutzer keinen Standardpfad verwenden, muß er halt den Pfad irgendwo von Hand angeben. Das erlaubt einem auch, mehrere Versionen auf der Platte zu haben und nach Bedarf explizit eine auszuwählen.
Code: Alles auswählen
import os
def ifilter_folders(base_dir, search_name):
for dir_name, sub_directories, filenames in os.walk(base_dir):
if search_name in sub_directories:
yield os.path.join(dir_name, search_name)
def main():
root_dir = 'D:\\'
seek_dir = 'VLC'
for dir_name in ifilter_folders(root_dir, seek_dir):
if os.path.exists(os.path.join(dir_name, 'vlc.exe'):
break
else:
print("vlc.exe not found")
return
print("vlc.exe found in %s" % dir_name)
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 10:31
von kodela
@sepplx123: Danke für Deine Infos für eine Suche über mehrere Laufwerke. Eine solche Suche ist für mich zwar nur von sekundärer Bedeutung. Es ging mir mehr um die grundsätzliche Frage nach dem obersten Punkt der Hierarchie für eine Suche. Das ist, wie ich jetzt weiß, das Rootverzeichnis eines Laufwerks. Ich werde aber trotzdem Deinen Hinweisen einmal nachgehen.
@Sirius3: Du hast mir ja eine (fast) fertige Lösung geliefert, Danke dafür. Zwei kleine Änderungen waren erforderlich. In der Zeile 13 fehlt am Ende eine schließende Klammer und der else-Zweig ab Zeile 14 muss noch um einen Tab eingerückt werden.
Eine Schwachstellen hat diese Lösung noch. Angenommen "C:\Program Files (x86)\VideoLAN\VLC" sei der zu findende Pfad und es gibt den Pfad "C:\VLC", in dem sich keine "vlc.exe" befindet, dann wird die Suche abgebrochen und damit der gesuchte Installationsordner nicht gefunden. Es müsste also weiter gesucht werden.
Hier stehe ich mit meinem Wissen noch vor einer Schranke. Auf Grund der Hinweise von @BlackJack weiß ich nun zwar, dass bei einem Rücksprung über "yield" ein Generatorobjekt zurück gegeben wird, über das man dann die Suche fortsetzen könnte. Das muss ja mit dem Code von Dir doch auch möglich sein, aber ich komme nicht dahinter, wie.
MfG, kodela
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 10:39
von BlackJack
@kodela: Das ``else`` muss *nicht* weiter eingerückt werden! Das gehört zur Schleife und nicht zum ``if``. Womit sich auch die Frage nach dem Weitersuchen erledigt, denn die Schleife läuft so lange bis alle passenden Verzeichnisse abgearbeitet sind.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Donnerstag 7. Januar 2016, 11:42
von kodela
@BlackJack: Oh, Danke. Da hatte ich mal wieder einen "Kurzschluss". Ein "for" mit einem else-Zweig, das habe ich noch nicht gesehen.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Freitag 8. Januar 2016, 00:02
von kodela
@DMD-OL: Ich habe Dein Thema mitbenützt, erweitert für die Suche nach Ordner mit einer bestimmten Datei. Dabei habe ich Dank der Hilfe von @BlackJack und @Sirius3 einiges dazu gelernt. Damit aber Deine Anfrage auch Beachtung findet, hier eine Lösung für die reine Ordnersuche, ausgedehnt auf jedes Vorkommen des zu suchenden Ordner im angegebenen Rootpfad. Hier das Ergebnis, das weitgehend dem Vorschlag von @Sirius3 entspricht:
Code: Alles auswählen
#!/usr/bin/env python35
# coding=utf-8
import os
def ifilter_folders(base_dir, search_name):
for dir_name, sub_directories, filenames in os.walk(base_dir):
if search_name in sub_directories:
yield os.path.join(dir_name, search_name)
def main():
root_dir = 'C:\\'
seek_dir = 'temp'
dir_name = ''
gefunden = False
for dir_name in ifilter_folders(root_dir, seek_dir):
if not gefunden:
print("Anzeige aller Pfade mit einem %s-Ordner:" % seek_dir)
print(dir_name)
gefunden = True
else:
# bezieht sich auf den for- und nicht auf den if-Block
if not gefunden:
print("Ein Ordner \'%s\' wurde nicht gefunden!" % seek_dir)
if __name__ == "__main__":
main()
Etwas möchte ich noch erwähnen. Ich habe diesen Code unter den Versionen 2.7.11 und 3.5 getestet. Dabei stellte ich fest, dass das Skript unter der Version 3.5 um den Faktor 5 schneller ausgeführt wurde (15 Sek. mit 2.7.11 und 3 Sek. mit 3.5). Wie erklärt sich das?
Gruß, kodela
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Freitag 8. Januar 2016, 00:07
von Sirius3
@kodela: ein else bei for ist unsinnig, wenn es im for kein break gibt. Wenn os.walk ein Verzeichnis findet, dann ist es mit großer Wahrscheinlichkeit auch bei os.path.exists noch da, die if-Abfrage ist also überflüssig; genauso ein os.path.join mit nur einem Argument. Das Escapen der einfachen Anführungszeichen ist unnötig und erschwert nur das Lesen.
Re: Bestimmten Ordner in C:\-Verzeichnisbaum finden
Verfasst: Freitag 8. Januar 2016, 00:58
von kodela
@Sirius3: Danke für Deine Hinweise. Ja, es ist richtig, dass das else am Ende der for-Schleife unsinnig ist. Der Sichtbereich für gefunden beschränkt sich ja nicht nur auf die for-Schleife.
Auch Dein zweiter Einwand ist richtig. Das ist mir auch selbst aufgefallen. Für die Rückgabe von def ifilter_folders() reicht ein yield dir_name aus. Ich wollte dies eben berichtigen, als dann aber Deine Antwort schon da war.