2017-03-10 11 views
3

Ich möchte ein Programm erstellen, das einige grundlegende Code verwendet, um durch einen Ordner zu lesen und mir sagen, wie viele Dateien in dem Ordner sind. Hier ist, wie ich das zur Zeit:Python os.walk zu bestimmten Ebene

import os 

folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3'] 
for stuff in folders: 
    for root, dirs, files in os.walk(stuff, topdown=True): 
     print("there are", len(files), "files in", root) 

Dies funktioniert gut, bis es mehrere Ordner im „main“ -Ordner sind, da es eine lange, junky Liste der Dateien aufgrund der schlechten Ordner/Dateiverwaltung zurückkehren kann. Ich möchte also höchstens auf die zweite Ebene gehen. Beispiel:

Main Folder 
---file_i_want 
---file_i_want 
---Sub_Folder 
------file_i_want <--* 
------file_i want <--* 
------Sub_Folder_2 
---------file_i_dont_want 
---------file_i_dont_want 

Ich weiß, wie man mit einem break nur der ersten Ebene zu gehen und mit del dirs[:] genommen von this post und also this post.

import os 
import pandas as pd 

folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3'] 
for stuff in folders: 
    for root, dirs, files in os.walk(stuff, topdown=True): 
     print("there are", len(files), "files in", root) 
     del dirs[:] # or a break here. does the same thing. 

Aber egal, meine Suche kann ich nicht herausfinden, wie man zwei Schichten tief geht. Ich verstehe einfach nicht die anderen Beiträge oder etwas anderes? Ich dachte etwas wie del dirs[:2], aber ohne Erfolg. Kann mich jemand führen oder mir erklären, wie ich das erreichen kann?

+0

'dirs' sind alle Verzeichnisse im aktuellen Verzeichnis, es ist nicht die Tiefe des Ordnerbaums. –

+0

@PeterWood, ah! Das macht Sinn. So, jetzt verstehe ich, warum 'del dirs [: 2]' ist dumm ... – MattR

+0

Es sieht aus wie Sie Python 3 verwenden. Ist das korrekt? –

Antwort

5

könnten Sie tun, wie folgt:

for root,dirs,files in os.walk(stuff): 
    if root[len(stuff)+1:].count(os.sep)<2: 
     for f in files: 
      print(os.path.join(root,f)) 

Schlüssel ist: if root[len(stuff)+1:].count(os.sep)<2

Es stuff + Separator aus root entfernt, so ergibt sich in Bezug auf stuff. Zählen Sie einfach die Anzahl der Dateitrennzeichen und geben Sie die Bedingung nur ein, wenn Sie 0 oder 1 Trennzeichen erhalten.

Natürlich scannt es immer noch die gesamte Dateistruktur, aber wenn es nicht sehr tief ist, wird es funktionieren.

Eine andere Lösung wäre, nur rekursiv os.listdir (mit Verzeichnisprüfung) mit einer maximalen Rekursionsebene zu verwenden, aber das ist ein wenig komplizierter, wenn Sie es nicht brauchen. Da es nicht so schwer ist, hier ist eine Implementierung:

def scanrec(root): 
    rval = [] 

    def do_scan(start_dir,output,depth=0): 
     for f in os.listdir(start_dir): 
      ff = os.path.join(start_dir,f) 
      if os.path.isdir(ff): 
       if depth<2: 
        do_scan(ff,output,depth+1) 
      else: 
       output.append(ff) 

    do_scan(root,rval,0) 
    return rval 

print(scanrec(stuff)) # prints the list of files not below 2 deep 

Hinweis: os.listdir und os.path.isfile ausführen 2 stat Anrufe so nicht optimal. In Python 3.5 könnte die Verwendung von os.scandir diesen doppelten Aufruf vermeiden.

+0

Das ist, was ich wollte. und ich schätze die "Key is" Aussage sehr. Könnten Sie mir bitte etwas erläutern oder auf eine Dokumentation hinweisen, wie Sie zu dieser Antwort gekommen sind? Ich bin fest, warum die Klammern in 'root [len (stuff ...]' und was '.count (os.sep)' tut. Vielen Dank. – MattR

+0

Warum nicht 'brechen' wenn 'root [len (stuff) + 1:]. Count (os.sep)> = 2'? Wenn das nach oben geht, gilt das für alle anderen Werte von "root". –

+0

@DavidCullen guter Punkt. Ich habe nicht darüber nachgedacht das funktioniert eigentlich nicht, es scheint nur für Verzeichnisse zu gelten. –

1

Sie können die Separatoren zählen und wenn es zwei Ebenen tief ist, den Inhalt dirs löschen, so ist walk nicht tiefer Rekursion:

import os 

MAX_DEPTH = 2 
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3'] 
for stuff in folders: 
    for root, dirs, files in os.walk(stuff, topdown=True): 
     print("there are", len(files), "files in", root) 
     if root.count(os.sep) - stuff.count(os.sep) == MAX_DEPTH - 1: 
      del dirs[:] 

Python documentation Staaten folgende über das Verhalten:

Wenn topdown True ist, kann der Aufrufer die Liste der dirnames an Ort und Stelle ändern (vielleicht mit Del- oder Slice-Zuweisung), und walk() wird nur in die Unterverzeichnisse rekurrieren, deren Namen in dirnames verbleiben; Dies kann verwendet werden, um die Suche zu beschneiden, eine bestimmte Reihenfolge des Besuchs aufzuerlegen oder sogar walk() über Verzeichnisse, die der Aufrufer erstellt oder umbenennt, zu informieren, bevor er wieder mit walk() fortfährt.

Beachten Sie, dass Sie die in der folders vorhandenen Separatoren berücksichtigen müssen. Zum Beispiel, wenn y:\path1 gegangen wird, ist root y:\path, aber Sie wollen die Rekursion dort nicht stoppen.

+0

Vielen Dank für die Hinweise auf die Dokumentation! ist es richtig, dass 'root.count (os.sep)' das '' \\ '' im root zählt? – MattR

+1

@MattR: Ja, es zählt \ (oder was immer das os-spezifische Trennzeichen ist) in der Wurzel, von der wir die im ursprünglichen Ordner vorhandenen Trennzeichen subtrahieren müssen. – niemmi

Verwandte Themen