Danh sách cây thư mục trong Python


Câu trả lời:


615

Đây là một cách để duyệt qua mọi tệp và thư mục trong cây thư mục:

import os

for dirname, dirnames, filenames in os.walk('.'):
    # print path to all subdirectories first.
    for subdirname in dirnames:
        print(os.path.join(dirname, subdirname))

    # print path to all filenames.
    for filename in filenames:
        print(os.path.join(dirname, filename))

    # Advanced usage:
    # editing the 'dirnames' list will stop os.walk() from recursing into there.
    if '.git' in dirnames:
        # don't go into any .git directories.
        dirnames.remove('.git')

19
Và nếu bạn chạy mã này (như hiện tại) từ Python Shell, hãy nhớ rằng Ctrl + C sẽ tạm dừng đầu ra cho shell đã nói. ;)
gary

41
Điều này sẽ liệt kê đệ quy các tệp và thư mục
rds

Bạn thậm chí có thể chỉnh sửa danh sách dirnames để ngăn nó đệ quy xuống một số đường dẫn.
bugloaf

8
@ Clément "Khi topdown là True, người gọi có thể sửa đổi danh sách dirnames tại chỗ (có thể sử dụng phép gán del hoặc lát) và walk () sẽ chỉ lặp lại vào các thư mục con có tên vẫn còn trong dirnames; tìm kiếm, áp đặt một thứ tự cụ thể của việc truy cập hoặc thậm chí để thông báo cho walk () về các thư mục mà người gọi tạo hoặc đổi tên trước khi nó tiếp tục lại walk (). " từ docs.python.org/2/library/os.html#os.walk
bugloaf

Cách đơn giản hơn để bỏ qua một số thư mục là không thêm chúng vào dirnames ở vị trí đầu tiênfor subdirname in dirnames: if subdirname != '.git'
smci

537

Bạn có thể dùng

os.listdir(path)

Để tham khảo và nhiều chức năng os xem tại đây:


1
Vâng, câu hỏi ban đầu chỉ đủ mơ hồ để không biết liệu họ có muốn một giải pháp đệ quy hay không. "tất cả các tệp trong một thư mục" có thể được hiểu là đệ quy.
Tommy

3
@ Mẹ ơi, một thư mục của người dùng là một cấu trúc dữ liệu được xác định rõ ràng và nó đề cập đến "ls" chứ không phải là "ls -R". Ngoài ra, hầu hết tất cả các công cụ UNIX không hoạt động đệ quy theo mặc định. Tôi không biết người hỏi có ý gì nhưng những gì anh ta viết thì rõ ràng.
Torsten Bronger

os.scandirTuy nhiên, tài liệu python 3 bảo bạn sử dụng thay vào đó, vì trong nhiều trường hợp, nó cho phép bạn ngăn chặn các cuộc gọi hệ thống, cho phép tăng tốc miễn phí (cả IPC và IO đều chậm).
Jappie Kerk

5
listdir cung cấp cho bạn tên tệp duy nhất trong thư mục, có phương thức nào để có đường dẫn đầy đủ không?
greperror

1
@greperror Bạn có thể sử dụng os.path.abspath để có được đường dẫn đầy đủ. Ngoài ra, để kiểm tra xem một đường dẫn cụ thể có phải là một tệp hay không, hãy sử dụng os.path.isfile hoặc os.path.isdir.
Aleksandar

111

Đây là một chức năng trợ giúp tôi sử dụng khá thường xuyên:

import os

def listdir_fullpath(d):
    return [os.path.join(d, f) for f in os.listdir(d)]

3
Một máy phát điện sẽ tốt hơn.
Robert Siemer

1
@RobertSiemer phụ thuộc vào cách sử dụng. Trong nhiều trường hợp, một danh sách sẽ tốt hơn, nhưng tôi đoán một trình tạo linh hoạt hơn vì nó có thể được chuyển đổi thành một danh sách. Nó phụ thuộc vào việc bạn đang tìm kiếm, tính linh hoạt hoặc một cái gì đó sắp xếp hợp lý hơn một chút.
James Mchugh

3
Đã mười năm, nhưng tôi nghĩ rằng tôi đã làm theo cách này bởi vì os.listdir () trả về một danh sách và tôi đã bắt chước điều đó.
Giltay

82
import os

for filename in os.listdir("C:\\temp"):
    print  filename

16
r'C:\temp'rõ ràng hơn và được ưu tiên hơn "C:\\temp"Rawstrings thích hợp hơn cho dấu gạch chéo ngược.
smci

13

Nếu bạn cần khả năng globbing, có một mô-đun cho rằng là tốt. Ví dụ:

import glob
glob.glob('./[0-9].*')

sẽ trở lại một cái gì đó như:

['./1.gif', './2.txt']

Xem tài liệu ở đây .


10

Thử cái này:

import os
for top, dirs, files in os.walk('./'):
    for nm in files:       
        print os.path.join(top, nm)

Trong một dòng: [top + os.sep + f cho top, dirs, tệp trong os.walk ('./') cho f trong tệp]
J. Peterson

9

Đối với các tệp trong thư mục làm việc hiện tại mà không chỉ định đường dẫn

Python 2.7:

import os
os.listdir(os.getcwd())

Python 3.x:

import os
os.listdir()

Cảm ơn Stam Kaly đã bình luận về python 3.x


5
os.listdir()liệt kê các thành phần trong thư mục hiện tại theo mặc định! Vì vậy, không cần os.getcwd():)
Stam Kaly

Làm thế nào tôi sẽ làm điều này? Khi tôi sử dụng >>> os.listdir () mà không có đối số, tôi nhận được: TypeError: listdir () nhận chính xác 1 đối số (0 đã cho)
Kỹ sư Dave

2
Tôi giả sử bạn đang chạy trên 2.7. Điều này đã được thêm vào 3.x
Stam Kaly

5

Thực hiện đệ quy

import os

def scan_dir(dir):
    for name in os.listdir(dir):
        path = os.path.join(dir, name)
        if os.path.isfile(path):
            print path
        else:
            scan_dir(path)

3

Tôi đã viết một phiên bản dài, với tất cả các tùy chọn tôi có thể cần: http://sam.nipl.net/code/python/find.py

Tôi đoán nó cũng sẽ phù hợp ở đây:

#!/usr/bin/env python

import os
import sys

def ls(dir, hidden=False, relative=True):
    nodes = []
    for nm in os.listdir(dir):
        if not hidden and nm.startswith('.'):
            continue
        if not relative:
            nm = os.path.join(dir, nm)
        nodes.append(nm)
    nodes.sort()
    return nodes

def find(root, files=True, dirs=False, hidden=False, relative=True, topdown=True):
    root = os.path.join(root, '')  # add slash if not there
    for parent, ldirs, lfiles in os.walk(root, topdown=topdown):
        if relative:
            parent = parent[len(root):]
        if dirs and parent:
            yield os.path.join(parent, '')
        if not hidden:
            lfiles   = [nm for nm in lfiles if not nm.startswith('.')]
            ldirs[:] = [nm for nm in ldirs  if not nm.startswith('.')]  # in place
        if files:
            lfiles.sort()
            for nm in lfiles:
                nm = os.path.join(parent, nm)
                yield nm

def test(root):
    print "* directory listing, with hidden files:"
    print ls(root, hidden=True)
    print
    print "* recursive listing, with dirs, but no hidden files:"
    for f in find(root, dirs=True):
        print f
    print

if __name__ == "__main__":
    test(*sys.argv[1:])

3

Đây là một lựa chọn khác.

os.scandir(path='.')

Nó trả về một iterator của các đối tượng os.DirEntry tương ứng với các mục (cùng với thông tin thuộc tính tệp) trong thư mục được cung cấp bởi đường dẫn.

Thí dụ:

with os.scandir(path) as it:
    for entry in it:
        if not entry.name.startswith('.'):
            print(entry.name)

Sử dụng scandir () thay cho listdir () có thể làm tăng đáng kể hiệu năng của mã cũng cần loại tệp hoặc thông tin thuộc tính tệp , vì các đối tượng os.DirEntry lộ thông tin này nếu hệ điều hành cung cấp nó khi quét thư mục. Tất cả các phương thức os.DirEntry có thể thực hiện một cuộc gọi hệ thống, nhưng is_dir () và is_file () thường chỉ yêu cầu một cuộc gọi hệ thống cho các liên kết tượng trưng; os.DirEntry.stat () luôn yêu cầu một cuộc gọi hệ thống trên Unix nhưng chỉ yêu cầu một liên kết tượng trưng trên Windows.

Python Documents


3

Mặc dù os.listdir()rất tốt để tạo danh sách tên tệp và thư mục, nhưng bạn thường muốn làm nhiều hơn một khi bạn có những tên đó - và trong Python3, pathlib làm cho các công việc khác trở nên đơn giản. Hãy xem và xem bạn có thích nó nhiều như tôi không.

Để liệt kê nội dung dir, xây dựng một đối tượng Path và lấy iterator:

In [16]: Path('/etc').iterdir()
Out[16]: <generator object Path.iterdir at 0x110853fc0>

Nếu chúng ta chỉ muốn một danh sách tên của những thứ:

In [17]: [x.name for x in Path('/etc').iterdir()]
Out[17]:
['emond.d',
 'ntp-restrict.conf',
 'periodic',

Nếu bạn chỉ muốn các thư mục:

In [18]: [x.name for x in Path('/etc').iterdir() if x.is_dir()]
Out[18]:
['emond.d',
 'periodic',
 'mach_init.d',

Nếu bạn muốn tên của tất cả các tệp conf trong cây đó:

In [20]: [x.name for x in Path('/etc').glob('**/*.conf')]
Out[20]:
['ntp-restrict.conf',
 'dnsextd.conf',
 'syslog.conf',

Nếu bạn muốn một danh sách các tệp conf trong cây> = 1K:

In [23]: [x.name for x in Path('/etc').glob('**/*.conf') if x.stat().st_size > 1024]
Out[23]:
['dnsextd.conf',
 'pf.conf',
 'autofs.conf',

Giải quyết các đường dẫn tương đối trở nên dễ dàng:

In [32]: Path('../Operational Metrics.md').resolve()
Out[32]: PosixPath('/Users/starver/code/xxxx/Operational Metrics.md')

Điều hướng với một Đường dẫn khá rõ ràng (mặc dù không mong đợi):

In [10]: p = Path('.')

In [11]: core = p / 'web' / 'core'

In [13]: [x for x in core.iterdir() if x.is_file()]
Out[13]:
[PosixPath('web/core/metrics.py'),
 PosixPath('web/core/services.py'),
 PosixPath('web/core/querysets.py'),

1

Một lót đẹp để liệt kê chỉ các tệp đệ quy. Tôi đã sử dụng điều này trong chỉ thị setup.py pack_data:

import os

[os.path.join(x[0],y) for x in os.walk('<some_directory>') for y in x[2]]

Tôi biết đó không phải là câu trả lời cho câu hỏi, nhưng có thể có ích


1

Đối với Python 2

#!/bin/python2

import os

def scan_dir(path):
    print map(os.path.abspath, os.listdir(pwd))

Đối với Python 3

Đối với bộ lọc và bản đồ, bạn cần bọc chúng bằng list ()

#!/bin/python3

import os

def scan_dir(path):
    print(list(map(os.path.abspath, os.listdir(pwd))))

Đề xuất bây giờ là bạn thay thế việc sử dụng bản đồ và bộ lọc của mình bằng các biểu thức của trình tạo hoặc danh sách hiểu:

#!/bin/python

import os

def scan_dir(path):
    print([os.path.abspath(f) for f in os.listdir(path)])

1

Đây là phiên bản Pythonic một dòng:

import os
dir = 'given_directory_name'
filenames = [os.path.join(os.path.dirname(os.path.abspath(__file__)),dir,i) for i in os.listdir(dir)]

Mã này liệt kê đường dẫn đầy đủ của tất cả các tệp và thư mục trong tên thư mục đã cho.


Cảm ơn Saleh, nhưng mã của bạn đã không hoạt động đầy đủ và mã đã hoạt động được sửa đổi như sau: 'dir =' give_directory_name 'filenames = [os.path.abspath (os.path.join (dir, i)) cho tôi trong os.listdir (dir)] '
HassanSh__3571619

1

Tôi biết đây là một câu hỏi cũ. Đây là một cách gọn gàng tôi đã gặp nếu bạn đang sử dụng máy liunx.

import subprocess
print(subprocess.check_output(["ls", "/"]).decode("utf8"))

0
#import modules
import os

_CURRENT_DIR = '.'


def rec_tree_traverse(curr_dir, indent):
    "recurcive function to traverse the directory"
    #print "[traverse_tree]"

    try :
        dfList = [os.path.join(curr_dir, f_or_d) for f_or_d in os.listdir(curr_dir)]
    except:
        print "wrong path name/directory name"
        return

    for file_or_dir in dfList:

        if os.path.isdir(file_or_dir):
            #print "dir  : ",
            print indent, file_or_dir,"\\"
            rec_tree_traverse(file_or_dir, indent*2)

        if os.path.isfile(file_or_dir):
            #print "file : ",
            print indent, file_or_dir

    #end if for loop
#end of traverse_tree()

def main():

    base_dir = _CURRENT_DIR

    rec_tree_traverse(base_dir," ")

    raw_input("enter any key to exit....")
#end of main()


if __name__ == '__main__':
    main()

5
Câu hỏi này đã có một câu trả lời hoàn toàn tốt, không cần phải trả lời lại
Mike Pennington

0

FYI Thêm bộ lọc mở rộng hoặc mở rộng tệp nhập os

path = '.'
for dirname, dirnames, filenames in os.walk(path):
    # print path to all filenames with extension py.
    for filename in filenames:
        fname_path = os.path.join(dirname, filename)
        fext = os.path.splitext(fname_path)[1]
        if fext == '.py':
            print fname_path
        else:
            continue

0

Nếu hình tôi sẽ ném cái này vào. Cách đơn giản và bẩn để thực hiện tìm kiếm ký tự đại diện.

import re
import os

[a for a in os.listdir(".") if re.search("^.*\.py$",a)]

0

Dưới đây mã sẽ liệt kê các thư mục và các tập tin trong thư mục

def print_directory_contents(sPath):
        import os                                       
        for sChild in os.listdir(sPath):                
            sChildPath = os.path.join(sPath,sChild)
            if os.path.isdir(sChildPath):
                print_directory_contents(sChildPath)
            else:
                print(sChildPath)

0

Phiên bản làm việc với tôi là một phiên bản sửa đổi từ câu trả lời của Saleh ở trên.

Mã như sau:

"dir = 'give_directory_name' filenames = [os.path.abspath (os.path.join (dir, i)) cho tôi trong os.listdir (dir)]"

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.