Verzeichnistiefe ermitteln

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
Holger Chapman
User
Beiträge: 26
Registriert: Samstag 12. Juli 2014, 01:59

Donnerstag 22. Februar 2018, 23:48

Hallo,

ich möchte gern die Tiefe eines Verzeichnisses ermitteln. Das heißt: Ich will wissen, wie viele Unterverzeichnis-Ebenen ein Verzeichnis hat. - Könnt ihr mir da helfen?

Zum besseren Verständnis:
Ein Verzeichnis ohne Unterverzeichnis soll die Tiefe 0 haben.
Ein Verzeichnis mit mindestens einem Unterverzeichnis (aber ohne ein Unterunterverzeichnis) soll die Tiefe 1 haben.
Ein Verzeichnis mit mindestens einem Unterunterverzeichnis (aber ohne ein Unterunterunterverzeichnis) soll die Tiefe 2 haben.
Ein Verzeichnis mit mindestens einem Unterunterunterverzeichnis (aber ohne ein Unterunterunterunterverzeichnis) soll die Tiefe 3 haben.
Usw.

Es läuft vermutlich darauf hinaus, dass ich beim rekursiven Durchlaufen einer Verzeichnisstruktur zählen will, welche die maximal durchlaufene Rekursionsstufe ist.

Hat jemand von euch eine Idee, wie sich das umsetzen lässt?

Vielen Dank!


Holger
Sirius3
User
Beiträge: 7788
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 23. Februar 2018, 00:05

@Holger Chapman: was hast Du denn schon versucht? `os.walk` ist Dein Freund.
Holger Chapman
User
Beiträge: 26
Registriert: Samstag 12. Juli 2014, 01:59

Samstag 24. Februar 2018, 08:58

Hallo Sirius3,
Sirius3 hat geschrieben:@Holger Chapman: was hast Du denn schon versucht? `os.walk` ist Dein Freund.
Ich habe das Folgende probiert, aber das liefert einen viel zu hohen Wert zurück. - Und irgendwie habe ich das Gefühl, ich mache es viel komplizierter als nötig.
Der Fehler ist wohl, dass der Wert für "depth" nicht reduziert wird, wenn der Weg in einen Unterverzeichniszweig sich als unnötig erwiesen hat, weil darin nicht das "tiefste" Unter-Unterverzeichnis war. Aber ich habe noch nicht die passende Stelle/Bedingung gefunden, um das abzufragen.

Vielleicht kann mir hier jemand helfen?

Danke und schönen Gruß


Holger

Code: Alles auswählen

#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import os

def get_subdirs(dir, depth):
    '''
    returns a) list of subdirs + b) new maximum depth for ...
    ... a) given dir ('dir') and b) current directory depth ('depth')
    '''
    # returns list of subdirs
    print "start: get_subdirs('{}', {})".format(dir, depth)
    subdirs=[]
    for diritself, subdirs, files in os.walk(dir):
        if not subdirs==[]:
            # there's at least one subdir
            depth = depth + 1
            for subdir in subdirs:
                get_subdirs(subdir, depth)
    return subdirs, depth

# main

testdir='test'
maxdepth = 0  # will be increased later on
subdirs, maxdepth = get_subdirs(testdir, maxdepth)
print "maximum subdir depth of '{}': {}".format(testdir, maxdepth)
__deets__
User
Beiträge: 2858
Registriert: Mittwoch 14. Oktober 2015, 14:29

Samstag 24. Februar 2018, 10:36

Ich halte os.walk genau hier nicht für deinen Freund. Denn es nimmt genau den Aspekt aus der Logik, der für dein Problem der Lösungsansatz ist: Rekursion. Das Problem wird trivial wenn man sich eine eigene Traversal-Funktion schreibt die skizziert so aussieht:

Code: Alles auswählen

def dir_depth(path):
      subdirs = subdirs_of_dir(path)
      if not subdirs:
            return 0
      return max(dir_depth(sd) for sd in subdirs) + 1
Holger Chapman
User
Beiträge: 26
Registriert: Samstag 12. Juli 2014, 01:59

Samstag 24. Februar 2018, 15:37

__deets__ hat geschrieben:Ich halte os.walk genau hier nicht für deinen Freund. Denn es nimmt genau den Aspekt aus der Logik, der für dein Problem der Lösungsansatz ist: Rekursion. Das Problem wird trivial wenn man sich eine eigene Traversal-Funktion schreibt die skizziert so aussieht [...]
Danke! - Folgendes scheint zu funktionieren (wobei ich mir noch Gedanken darüber machen muss, wie ich symbolische Links und Ordner mit fehlenden Zugriffsrechten behandeln will):

Code: Alles auswählen

#!/usr/bin/env python2

import os

def subdirs_of_dir(path):
    return [path + '/' + name for name in os.listdir(path)
        if os.path.isdir(os.path.join(path, name))]

def dir_depth(path):
    subdirs = subdirs_of_dir(path)
    if not subdirs:
        return 0
    return max(dir_depth(sd) for sd in subdirs) + 1

dirpath = '/home/holgerc/test'
print dir_depth(dirpath)
Schönen Gruß


Holger
__deets__
User
Beiträge: 2858
Registriert: Mittwoch 14. Oktober 2015, 14:29

Samstag 24. Februar 2018, 16:11

Bitte os.path.join verwenden statt strings zusammen+zu+plussen. Aber schön das es klappt.
Holger Chapman
User
Beiträge: 26
Registriert: Samstag 12. Juli 2014, 01:59

Samstag 24. Februar 2018, 17:59

__deets__ hat geschrieben:Bitte os.path.join verwenden statt strings zusammen+zu+plussen. Aber schön das es klappt.
Stimmt, danke für den Hinweis. (Und ein hart kodiertes '/' ist sowieso doof, wenn überhaupt hätte ich besser os.sep verwendet.)
Sirius3
User
Beiträge: 7788
Registriert: Sonntag 21. Oktober 2012, 17:20

Samstag 24. Februar 2018, 20:59

@__deets__: `os.walk` erledigt die Rekursion halt schon für einen:

Code: Alles auswählen

def dir_depth(path):
    return max(p.count(os.sep) for p, _, _ in os.walk(path)) - path.count(os.sep)
Holger Chapman
User
Beiträge: 26
Registriert: Samstag 12. Juli 2014, 01:59

Montag 26. Februar 2018, 22:22

Sirius3 hat geschrieben:

Code: Alles auswählen

def dir_depth(path):
    return max(p.count(os.sep) for p, _, _ in os.walk(path)) - path.count(os.sep)
Wow, sehr schön und kurz. Das bestätigt meine anfängliche Vermutung: "irgendwie habe ich das Gefühl, ich mache es viel komplizierter als nötig".

Danke!
Antworten