Utiliser os.walk () pour parcourir récursivement les répertoires en Python

153

Je veux naviguer du répertoire racine vers tous les autres répertoires à l'intérieur et imprimer le même.

Voici mon 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 ""

Et voici mon 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

Ci-dessus, .et ./packagedemosont des répertoires.

Cependant, je dois imprimer le O / P de la manière suivante:

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

Ci-dessus, Aet Bsont des répertoires et le reste sont des fichiers.

Nitaai
la source
6
Je voudrais ajouter ce petit post ici, sur le pouvoir de python: >>> print 2 * '-' ----
Nitaai

Réponses:

231

Cela vous donnera le résultat souhaité

#!/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)
Ajay
la source
6
path = os.path.relpath (root, basepath) .split (os.sep)
Semprini
9
@Ajay être paranoïaque et toujours faire os.walk(u".")car les chemins peuvent être Unicode.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Mieux encore,os.path.curdir
Jir
J'utilisais os.path.walkdepuis un moment, c'est donc os.walknouveau pour moi! Fèves fraîches.
Tom
@Semprini qu'est-ce qui est basepathégal dans votre code?
stelios
23

essaye ça:

#!/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))

vous obtiendrez ceci:

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
légendemohe
la source
Salut, j'aime vraiment ton script, mais c'est un peu trop compliqué pour le projet sur lequel je travaille, y a-t-il une chance que je puisse l'avoir comme une petite fonction, avec seulement l'argument -r présent?
jeff_h
comment l'imprimer dans un .txt? J'ai essayé print(FileTreeMaker().make(args),file=tree)mais ça me donne'charmap' codec can't encode characters in position 17-21: character maps to <undefined>
Luis Felipe
qu'est-ce que idc représente
voix
J'ai écrit quelque chose de similaire avec os.listdir()aussi. Le vôtre est bien meilleur; Je n'ai pas pu obtenir la bonne récursivité, cela ne fonctionnait que sur 2 ou 3 couches de profondeur. En fin de compte, j'ai décidé de réessayer à partir de zéro avec à la os.walk()place, ce qui, à mon avis, serait beaucoup plus approprié. Je suis surpris que vous ne l'ayez pas du tout utilisé ici.
voix du
11

Il existe des fonctions plus appropriées pour cela dans le ospackage. Mais si vous devez utiliser os.walk, voici ce que je propose

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)

production:

>>> walkdir('.')
.
---file3
---file2
---my.py
---file1
---A
------file2
------file1
---B
------file3
------file2
------file4
------file1
---__pycache__
------my.cpython-33.pyc
zaquest
la source
5
Alors, quelles sont les fonctions les plus appropriées? (en 3.5 si ça compte)
Al Lelopath
Désolé, aucune chance de me souvenir de ce que je voulais dire par là. C'est possible que je voulais dire, os.listdirmais la solution de @ ajay l'emporte.
zaquest
5

Vous pouvez utiliser os.walk, et c'est probablement la solution la plus simple, mais voici une autre idée à explorer:

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()

Vous pouvez reconnaître la documentation suivante à partir de la commande TREE dans le terminal Windows:

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.
Noctis Skytower
la source
5

Promenade récursive dans un répertoire où vous obtenez TOUS les fichiers de tous les répertoires du répertoire courant et vous obtenez TOUS les répertoires du répertoire actuel - car les codes ci-dessus n'ont pas de simplicité (à mon humble avis):

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))
Erhard Dinhobl
la source
3
Réponse la plus utile. Notez que os.path.join(root, filename)donne le chemin complet du fichier, même si le fichier est imbriqué dans plusieurs répertoires.
clw
4

Cela le fait pour les noms de dossier:

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]
Michael Lastufka
la source
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(".")
Deepak Kumar
la source
1

Étant donné le nom d'un dossier, parcourez toute sa hiérarchie de manière récursive.

#! /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')
yaniv
la source
4
Pas besoin d'appeler os.walk récursivement, car il aplatit déjà la récursivité. C'est pourquoi il renvoie l'argument folderName.
gwideman
1

Serait le meilleur moyen

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)
Rakesh Chaudhari
la source
Ne fonctionne pas pour moi dans Python3. Je suppose que l'erreur est dans dir + d, ce qui pourrait les concaténer sans séparateur de répertoire. Il est probablement préférable d'utiliser os.path.joinpour concer des répertoires avec des noms de fichiers
Zvika
0

Essayez ceci; facile

 #!/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)

======== SORTIE ci-dessous ========

 /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
harveyD
la source
À quoi sert le contrôle des chemins déjà parcourus? S'il s'agit de détecter les boucles causées par des liens, os.walk par défaut ne suit apparemment pas les liens. Y a-t-il une autre situation?
gwideman
0

Essaye ça:

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

Ici, je suppose que votre chemin est "." dans lequel se trouvent le root_file et d'autres répertoires. Donc, fondamentalement, nous itérons simplement dans l'arbre en utilisant l'appel next (), car notre os.walk n'est qu'une fonction générative. En faisant cela, nous pouvons enregistrer tous les noms de répertoires et de fichiers respectivement dans dir_names et file_names.

Parikshit Agarwal
la source
0

Vous pouvez également parcourir de manière récursive un dossier et répertorier tout son contenu en utilisant pathlib.Path ()

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)

Production:

example folder
    folder
        textfile3.txt
    textfile1.txt
    textfile2.txt
Fredz0r
la source
-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
niib
la source
Cela n'a pas l'air de traverser tout l'arbre.
Tous les travailleurs sont essentiels