Verwenden von os.walk () zum rekursiven Durchlaufen von Verzeichnissen in Python


151

Ich möchte vom Stammverzeichnis zu allen anderen Verzeichnissen darin navigieren und dasselbe drucken.

Hier ist mein Code:

#!/usr/bin/python

import os
import fnmatch

for root, dir, files in os.walk("."):
        print root
        print ""
        for items in fnmatch.filter(files, "*"):
                print "..." + items
        print ""

Und hier ist mein O / P:

.

...Python_Notes
...pypy.py
...pypy.py.save
...classdemo.py
....goutputstream-J9ZUXW
...latest.py
...pack.py
...classdemo.pyc
...Python_Notes~
...module-demo.py
...filetype.py

./packagedemo

...classdemo.py
...__init__.pyc
...__init__.py
...classdemo.pyc

Oben .und ./packagedemosind Verzeichnisse.

Ich muss das O / P jedoch folgendermaßen drucken:

A
---a.txt
---b.txt
---B
------c.out

Oben, Aund Bsind Verzeichnisse und der Rest sind Dateien.


6
Ich möchte diesen kleinen Beitrag hier über die Kraft von Python hinzufügen: >>> print 2 * '-' ----
Nitaai

Antworten:


228

Dadurch erhalten Sie das gewünschte Ergebnis

#!/usr/bin/python

import os

# traverse root directory, and list directories as dirs and files as files
for root, dirs, files in os.walk("."):
    path = root.split(os.sep)
    print((len(path) - 1) * '---', os.path.basename(root))
    for file in files:
        print(len(path) * '---', file)

6
path = os.path.relpath (root, basepath) .split (os.sep)
Semprini

9
@ Ajay sei paranoid und mache es immer, os.walk(u".")weil Pfade Unicode sein können.
Ciro Santilli 法轮功 冠状 病 六四 事件 24

3
Besser noch,os.path.curdir
Jir

Ich habe es os.path.walkeine Weile benutzt, also os.walkist es neu für mich! Kühle Bohnen.
Tom

@ Semprini was ist basepathgleich in deinem Code?
Stelios

23

Versuche dies:

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

"""FileTreeMaker.py: ..."""

__author__  = "legendmohe"

import os
import argparse
import time

class FileTreeMaker(object):

    def _recurse(self, parent_path, file_list, prefix, output_buf, level):
        if len(file_list) == 0 \
            or (self.max_level != -1 and self.max_level <= level):
            return
        else:
            file_list.sort(key=lambda f: os.path.isfile(os.path.join(parent_path, f)))
            for idx, sub_path in enumerate(file_list):
                if any(exclude_name in sub_path for exclude_name in self.exn):
                    continue

                full_path = os.path.join(parent_path, sub_path)
                idc = "┣━"
                if idx == len(file_list) - 1:
                    idc = "┗━"

                if os.path.isdir(full_path) and sub_path not in self.exf:
                    output_buf.append("%s%s[%s]" % (prefix, idc, sub_path))
                    if len(file_list) > 1 and idx != len(file_list) - 1:
                        tmp_prefix = prefix + "┃  "
                    else:
                        tmp_prefix = prefix + "    "
                    self._recurse(full_path, os.listdir(full_path), tmp_prefix, output_buf, level + 1)
                elif os.path.isfile(full_path):
                    output_buf.append("%s%s%s" % (prefix, idc, sub_path))

    def make(self, args):
        self.root = args.root
        self.exf = args.exclude_folder
        self.exn = args.exclude_name
        self.max_level = args.max_level

        print("root:%s" % self.root)

        buf = []
        path_parts = self.root.rsplit(os.path.sep, 1)
        buf.append("[%s]" % (path_parts[-1],))
        self._recurse(self.root, os.listdir(self.root), "", buf, 0)

        output_str = "\n".join(buf)
        if len(args.output) != 0:
            with open(args.output, 'w') as of:
                of.write(output_str)
        return output_str

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-r", "--root", help="root of file tree", default=".")
    parser.add_argument("-o", "--output", help="output file name", default="")
    parser.add_argument("-xf", "--exclude_folder", nargs='*', help="exclude folder", default=[])
    parser.add_argument("-xn", "--exclude_name", nargs='*', help="exclude name", default=[])
    parser.add_argument("-m", "--max_level", help="max level",
                        type=int, default=-1)
    args = parser.parse_args()
    print(FileTreeMaker().make(args))

Sie werden dies bekommen:

root:.
[.]
┣━[.idea]
  ┣━[scopes]
    ┗━scope_settings.xml
  ┣━.name
  ┣━Demo.iml
  ┣━encodings.xml
  ┣━misc.xml
  ┣━modules.xml
  ┣━vcs.xml
  ┗━workspace.xml
┣━[test1]
  ┗━test1.txt
┣━[test2]
  ┣━[test2-2]
    ┗━[test2-3]
        ┣━test2
        ┗━test2-3-1
  ┗━test2
┣━folder_tree_maker.py
┗━tree.py

Hallo, ich liebe dein Skript wirklich, aber es ist etwas zu kompliziert für das Projekt, an dem ich arbeite. Gibt es eine Chance, dass ich es als eine kleine Funktion habe, bei der nur das Argument -r vorhanden ist?
Jeff_h

Wie drucke ich es in einer TXT? Ich habe es versucht, print(FileTreeMaker().make(args),file=tree)aber es gibt mir'charmap' codec can't encode characters in position 17-21: character maps to <undefined>
Luis Felipe

Wofür steht IDC?
Stimmen

Ich habe auch etwas Ähnliches mit geschrieben os.listdir(). Dein ist viel besser; Ich konnte die Rekursion nicht richtig machen, sie funktionierte nur 2 oder 3 Schichten tief. Am Ende habe ich mich entschlossen, es os.walk()stattdessen noch einmal von Grund auf zu versuchen , was ich für weitaus besser geeignet hielt. Ich bin überrascht, dass Sie es hier überhaupt nicht benutzt haben.
Stimmen

11

Es gibt dafür geeignetere Funktionen im osPaket. Aber wenn Sie verwenden müssen, os.walkist hier, was ich mit kommen

def walkdir(dirname):
    for cur, _dirs, files in os.walk(dirname):
        pref = ''
        head, tail = os.path.split(cur)
        while head:
            pref += '---'
            head, _tail = os.path.split(head)
        print(pref+tail)
        for f in files:
            print(pref+'---'+f)

Ausgabe:

>>> walkdir('.')
.
---file3
---file2
---my.py
---file1
---A
------file2
------file1
---B
------file3
------file2
------file4
------file1
---__pycache__
------my.cpython-33.pyc

5
Was sind also besser geeignete Funktionen? (in 3.5, wenn das wichtig ist)
Al Lelopath

Entschuldigung, keine Chance, sich daran zu erinnern, was ich damit gemeint habe. Es ist möglich, dass ich meinte, os.listdiraber die Lösung von @ ajay schlägt das.
Zaquest

5

Sie können verwenden os.walk, und das ist wahrscheinlich die einfachste Lösung, aber hier ist eine andere Idee zu untersuchen:

import sys, os

FILES = False

def main():
    if len(sys.argv) > 2 and sys.argv[2].upper() == '/F':
        global FILES; FILES = True
    try:
        tree(sys.argv[1])
    except:
        print('Usage: {} <directory>'.format(os.path.basename(sys.argv[0])))

def tree(path):
    path = os.path.abspath(path)
    dirs, files = listdir(path)[:2]
    print(path)
    walk(path, dirs, files)
    if not dirs:
        print('No subfolders exist')

def walk(root, dirs, files, prefix=''):
    if FILES and files:
        file_prefix = prefix + ('|' if dirs else ' ') + '   '
        for name in files:
            print(file_prefix + name)
        print(file_prefix)
    dir_prefix, walk_prefix = prefix + '+---', prefix + '|   '
    for pos, neg, name in enumerate2(dirs):
        if neg == -1:
            dir_prefix, walk_prefix = prefix + '\\---', prefix + '    '
        print(dir_prefix + name)
        path = os.path.join(root, name)
        try:
            dirs, files = listdir(path)[:2]
        except:
            pass
        else:
            walk(path, dirs, files, walk_prefix)

def listdir(path):
    dirs, files, links = [], [], []
    for name in os.listdir(path):
        path_name = os.path.join(path, name)
        if os.path.isdir(path_name):
            dirs.append(name)
        elif os.path.isfile(path_name):
            files.append(name)
        elif os.path.islink(path_name):
            links.append(name)
    return dirs, files, links

def enumerate2(sequence):
    length = len(sequence)
    for count, value in enumerate(sequence):
        yield count, count - length, value

if __name__ == '__main__':
    main()

Möglicherweise erkennen Sie die folgende Dokumentation am Befehl TREE im Windows-Terminal:

Graphically displays the folder structure of a drive or path.

TREE [drive:][path] [/F] [/A]

   /F   Display the names of the files in each folder.
   /A   Use ASCII instead of extended characters.

5

Rekursiver Spaziergang durch ein Verzeichnis, in dem Sie ALLE Dateien aus allen Verzeichnissen im aktuellen Verzeichnis und ALLE Verzeichnisse aus dem aktuellen Verzeichnis abrufen - da die obigen Codes keine Einfachheit haben (imho):

for root, dirs, files in os.walk(rootFolderPath):
    for filename in files:
        doSomethingWithFile(os.path.join(root, filename))
    for dirname in dirs:
        doSomewthingWithDir(os.path.join(root, dirname))

3
Hilfreichste Antwort. Beachten Sie, dass os.path.join(root, filename)der vollständige Pfad zur Datei angegeben wird, auch wenn die Datei in mehreren Verzeichnissen verschachtelt ist.
Clw

4

Dies geschieht für Ordnernamen:

def printFolderName(init_indent, rootFolder):
    fname = rootFolder.split(os.sep)[-1]
    root_levels = rootFolder.count(os.sep)
    # os.walk treats dirs breadth-first, but files depth-first (go figure)
    for root, dirs, files in os.walk(rootFolder):
        # print the directories below the root
        levels = root.count(os.sep) - root_levels
        indent = ' '*(levels*2)
        print init_indent + indent + root.split(os.sep)[-1]

3
#!/usr/bin/python

import os 

def tracing(a):
    global i>
    for item in os.listdir(a):
        if os.path.isfile(item):
            print i + item 
        else:
            print i + item 
            i+=i
            tracing(item)

i = "---"
tracing(".")

1

Gehen Sie bei einem Ordnernamen rekursiv durch die gesamte Hierarchie.

#! /usr/local/bin/python3
# findLargeFiles.py - given a folder name, walk through its entire hierarchy
#                   - print folders and files within each folder

import os

def recursive_walk(folder):
    for folderName, subfolders, filenames in os.walk(folder):
        if subfolders:
            for subfolder in subfolders:
                recursive_walk(subfolder)
        print('\nFolder: ' + folderName + '\n')
        for filename in filenames:
            print(filename + '\n')

recursive_walk('/name/of/folder')

4
Sie müssen os.walk nicht rekursiv aufrufen, da dies die Rekursion bereits abflacht. Aus diesem Grund wird das Argument folderName zurückgegeben.
Gwideman

1

Wäre der beste Weg

def traverse_dir_recur(dir):
    import os
    l = os.listdir(dir)
    for d in l:
        if os.path.isdir(dir + d):
            traverse_dir_recur(dir+  d +"/")
        else:
            print(dir + d)

Funktioniert nicht für mich in Python3. Ich dir + dgehe davon aus, dass der Fehler vorliegt, der sie möglicherweise ohne Verzeichnistrennzeichen betrifft. Es ist wahrscheinlich besser, os.path.joinVerzeichnisse mit Dateinamen zu
verknüpfen

0

Versuchen Sie dies; Einfaches

 #!/usr/bin/python
 import os
 # Creating an empty list that will contain the already traversed paths
 donePaths = []
 def direct(path):
       for paths,dirs,files in os.walk(path):
             if paths not in donePaths:
                    count = paths.count('/')
                    if files:
                          for ele1 in files:
                                print '---------' * (count), ele1
                    if dirs:
                          for ele2 in dirs:
                                print '---------' * (count), ele2
                                absPath = os.path.join(paths,ele2)
              # recursively calling the direct function on each directory
                                direct(absPath)
                   # adding the paths to the list that got traversed 
                                donePaths.append(absPath)

 path = raw_input("Enter any path to get the following Dir Tree ...\n")
 direct(path)

======== AUSGABE unten ========

 /home/test
 ------------------ b.txt
 ------------------ a.txt
 ------------------ a
 --------------------------- a1.txt
 ------------------ b
 --------------------------- b1.txt
 --------------------------- b2.txt
 --------------------------- cde
 ------------------------------------ cde.txt
 ------------------------------------ cdeDir
 --------------------------------------------- cdeDir.txt
 ------------------ c
 --------------------------- c.txt
 --------------------------- c1
 ------------------------------------ c1.txt
 ------------------------------------ c2.txt

Was ist der Sinn der Prüfung für bereits durchquerte Pfade? Wenn es darum geht, durch Links verursachte Schleifen zu erkennen, verwendet os.walk anscheinend standardmäßig keine Links. Gibt es eine andere Situation?
Gwideman

0

Versuche dies:

import os
root_name = next(os.walk("."))[0]
dir_names = next(os.walk("."))[1]
file_names = next(os.walk("."))[2]

Hier nehme ich Ihren Weg als "." in dem sich die root_file und andere Verzeichnisse befinden. Grundsätzlich iterieren wir also nur mit dem Aufruf next () durch den Baum, da unser os.walk nur eine generative Funktion ist. Auf diese Weise können wir alle Verzeichnis- und Dateinamen in dir_names bzw. file_names speichern.


0

Sie können auch rekursiv durch einen Ordner gehen und den gesamten Inhalt mit pathlib.Path () auflisten.

from pathlib import Path


def check_out_path(target_path, level=0):
    """"
    This function recursively prints all contents of a pathlib.Path object
    """
    def print_indented(folder, level):
        print('\t' * level + folder)

    print_indented(target_path.name, level)
    for file in target_path.iterdir():
        if file.is_dir():
            check_out_path(file, level+1)
        else:
            print_indented(file.name, level+1)


my_path = Path(r'C:\example folder')
check_out_path(my_path)

Ausgabe:

example folder
    folder
        textfile3.txt
    textfile1.txt
    textfile2.txt

-3
import os

os.chdir('/your/working/path/')
dir = os.getcwd()
list = sorted(os.listdir(dir))
marks = ""

for s_list in list:
    print marks + s_list
    marks += "---"
    tree_list = sorted(os.listdir(dir + "/" + s_list))
    for i in tree_list:
        print marks + i

Dies sieht nicht so aus, als würde es den ganzen Baum durchqueren.
Alle Arbeiter sind essentiell
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.