Sử dụng os.walk () để duyệt qua các thư mục trong Python


151

Tôi muốn điều hướng từ thư mục gốc đến tất cả các thư mục khác trong và in giống nhau.

Đây là mã của tôi:

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

Và đây là O / P của tôi:

.

...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

Trên đây, ../packagedemolà các thư mục.

Tuy nhiên, tôi cần in O / P theo cách sau:

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

Ở trên, ABlà các thư mục và phần còn lại là các tập tin.


6
Tôi muốn thêm bài đăng nhỏ này vào đây, về sức mạnh của trăn: >>> in 2 * '-' ----
Nitaai

Câu trả lời:


228

Điều này sẽ cho bạn kết quả mong muốn

#!/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 bị hoang tưởng và luôn luôn làm os.walk(u".")vì đường dẫn có thể là Unicode.
Ciro Santilli 郝海东 冠状 病 事件 法轮功

3
Vẫn tốt hơn,os.path.curdir
Jir

Tôi đã sử dụng được os.path.walkmột thời gian, vì vậy os.walknó là mới đối với tôi! Đậu nguội.
Tom

@Semprini có gì basepathbằng mã của bạn?
stelios

23

thử cái này:

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

bạn sẽ nhận được điều này:

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

Xin chào, tôi thực sự yêu thích kịch bản của bạn, nhưng nó hơi phức tạp đối với dự án tôi đang thực hiện, có khả năng nào tôi có thể có nó như một chức năng nhỏ, chỉ có đối số -r không?
jeff_h

Làm thế nào để in nó trong một .txt? Tôi đã thử print(FileTreeMaker().make(args),file=tree)nhưng nó mang lại cho tôi'charmap' codec can't encode characters in position 17-21: character maps to <undefined>
Luis Felipe

idc là viết tắt của từ gì
tiếng nói

Tôi đã viết một cái gì đó tương tự với os.listdir()quá. Của bạn là tốt hơn nhiều; Tôi không thể có được đệ quy đúng, nó chỉ hoạt động sâu 2 hoặc 3 lớp. Cuối cùng, tôi quyết định thử lại từ đầu os.walk()thay vào đó, điều mà tôi nghĩ sẽ phù hợp hơn nhiều. Tôi ngạc nhiên khi bạn không sử dụng nó ở đây.
lên tiếng

11

Có nhiều chức năng phù hợp hơn cho việc này trong osgói. Nhưng nếu bạn phải sử dụng os.walk, đây là những gì tôi nghĩ ra

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)

đầu ra:

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

5
Vậy chức năng nào phù hợp hơn? (trong 3,5 nếu có vấn đề)
Al Lelopath

Xin lỗi, không có cơ hội để nhớ những gì tôi có nghĩa là. Ý tôi là có thể os.listdirnhưng giải pháp của @ ajay đánh bại điều đó.
zaquest

5

Bạn có thể sử dụng os.walk, và đó có lẽ là giải pháp dễ nhất, nhưng đây là một ý tưởng khác để khám phá:

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

Bạn có thể nhận ra tài liệu sau từ lệnh TREE trong thiết bị đầu cuối 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

Đi bộ đệ quy qua một thư mục nơi bạn nhận được TẤT CẢ các tệp từ tất cả các thư mục trong thư mục hiện tại và bạn nhận được TẤT CẢ các thư mục từ thư mục hiện tại - vì các mã ở trên không có tính đơn giản (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
Câu trả lời hữu ích nhất. Lưu ý rằng os.path.join(root, filename)cung cấp đường dẫn đầy đủ đến tệp, ngay cả khi tệp được lồng trong một số thư mục.
clw 23/12/19

4

Điều này làm cho tên thư mục:

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

Đặt tên thư mục, đi qua toàn bộ hệ thống phân cấp của nó một cách đệ quy.

#! /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
Không cần phải gọi os.walk đệ quy, vì nó đã làm phẳng đệ quy. Đó là lý do tại sao nó trả về đối số thư mục.
gwideman

1

Sẽ là cách tốt nhất

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)

Không làm việc cho tôi trong Python3. Tôi giả sử lỗi là trong dir + dđó, có thể nối chúng mà không có dấu phân cách thư mục. Có lẽ tốt hơn để sử dụng os.path.joinđể nối các thư mục với tên tệp
Zvika

0

Hãy thử điều này; dễ dàng một

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

======== ĐẦU RA bên dưới ========

 /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

Điểm kiểm tra cho các đường dẫn đã đi qua là gì? Nếu đó là để phát hiện các vòng lặp gây ra bởi các liên kết, os.walk dường như mặc định không theo các liên kết. Có một số tình huống khác?
gwideman

0

Thử cái này:

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

Ở đây tôi giả sử đường dẫn của bạn là "." trong đó root_file và các thư mục khác ở đó. Vì vậy, về cơ bản, chúng ta chỉ lặp đi lặp lại trên toàn cây bằng cách sử dụng lệnh gọi next (), vì os.walk của chúng ta chỉ là hàm tạo. Bằng cách này, chúng ta có thể lưu tất cả các tên thư mục và tệp trong dir_names và file_names tương ứng.


0

Bạn cũng có thể đệ quy đi qua một thư mục và liệt kê tất cả nội dung của nó bằng 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)

Đầu ra:

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

Điều này không giống như nó đi qua toàn bộ cây.
Tất cả công nhân là cần thiết
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.