Usando os.walk () para percorrer diretórios recursivamente em Python


151

Eu quero navegar do diretório raiz para todos os outros diretórios dentro e imprimir o mesmo.

Aqui está o meu código:

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

E aqui está o meu 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

Acima, .e ./packagedemosão diretórios.

No entanto, preciso imprimir o O / P da seguinte maneira:

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

Acima, Ae Bsão diretórios e o restante são arquivos.


6
Gostaria de adicionar este pequeno post aqui, sobre o poder do python: >>> print 2 * '-' ----
Nitaai

Respostas:


228

Isso lhe dará o resultado desejado

#!/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
caminho = os.path.relpath (raiz, BasePath) .Split (os.sep)
Semprini

9
@Ajay seja paranóico e sempre acontece os.walk(u".")porque os caminhos podem ser Unicode.
Ciro Santilli # 24/14

3
Melhor ainda, #os.path.curdir
214

Eu estava usando os.path.walkpor um tempo, então os.walké novo para mim! Feijão fresco.
Tom

@Semprini o que é basepathigual no seu código?
Stelios

23

tente isto:

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

você receberá isto:

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

Olá, eu realmente amo o seu script, mas é um pouco complicado para o projeto em que estou trabalhando. Existe alguma chance de eu tê-lo como uma pequena função, com apenas o argumento -r presente?
jeff_h

como imprimi-lo em um .txt? Eu tentei print(FileTreeMaker().make(args),file=tree)mas dá-me'charmap' codec can't encode characters in position 17-21: character maps to <undefined>
Luis Felipe

o que é idc
voices

Também escrevi algo parecido os.listdir(). O seu é muito melhor; Não consegui acertar a recursão, apenas funcionou com 2 ou 3 camadas de profundidade. No final, decidi tentar novamente do zero os.walk(), o que achei muito mais adequado. Estou surpreso que você não tenha usado nada aqui.
vozes

11

Existem funções mais adequadas para isso no ospacote. Mas se você tiver que usar os.walk, aqui está o que eu proponho

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)

resultado:

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

5
Então, quais são as funções mais adequadas? (em 3,5 se o que importa)
Al Lelopath

Desculpe, sem chance de lembrar o que eu quis dizer com isso. É possível que eu quis dizer isso, os.listdirmas a solução da @ ajay supera isso.
Zaquest

5

Você pode usar os.walk, e essa é provavelmente a solução mais fácil, mas aqui está outra idéia para explorar:

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

Você pode reconhecer a seguinte documentação do comando TREE no terminal do 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.

5

Percurso recursivo por um diretório em que você obtém TODOS os arquivos de todos os diretórios do diretório atual e obtém TODOS os diretórios do diretório atual - porque os códigos acima não têm uma simplicidade (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
Resposta mais útil. Observe que os.path.join(root, filename)fornece o caminho completo para o arquivo, mesmo se o arquivo estiver aninhado em vários diretórios.
Clw

4

Faz isso para nomes de pastas:

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

Dado o nome de uma pasta, percorra toda a sua hierarquia recursivamente.

#! /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
Não há necessidade de chamar os.walk de forma recursiva, pois ela já aplana a recursão. É por isso que retorna o argumento folderName.
gwideman

1

Seria a melhor maneira

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)

Não está funcionando para mim no Python3. Presumo que o erro esteja dir + d, o que pode concatená-los sem separador de diretório. Provavelmente é melhor usar os.path.joinpara concatir diretórios com nomes de arquivos
Zvika

0

Tente isso; Facil

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

======== SAÍDA abaixo ========

 /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

Qual é o sentido da verificação de caminhos já percorridos? Se é para detectar loops causados ​​por links, o os.walk aparentemente usa como padrão não seguir os links. Existe alguma outra situação?
gwideman

0

Tente o seguinte:

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

Aqui estou assumindo o seu caminho como "." no qual o root_file e outros diretórios estão lá. Portanto, basicamente estamos iterando por toda a árvore usando a chamada next (), pois nosso os.walk é apenas uma função generativa. Ao fazer isso, podemos salvar todos os nomes de diretório e arquivos em dir_names e file_names, respectivamente.


0

Você também pode percorrer recursivamente uma pasta e lista todo o seu conteúdo usando 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)

Resultado:

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

Isso não parece atravessar a árvore inteira.
Todos os trabalhadores são essenciais
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.