Daftar direktori-pohon dengan Python


Jawaban:


615

Ini adalah cara untuk melintasi setiap file dan direktori di pohon direktori:

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
Dan jika Anda menjalankan kode ini (sebagaimana adanya) dari Python Shell, ingat bahwa Ctrl + C akan menghentikan output ke shell tersebut. ;)
gary

41
Ini akan mendaftarkan file dan direktori secara rekursif
rds

Anda bahkan dapat mengedit daftar direktori untuk mencegahnya mengulangi beberapa jalur.
bugloaf

8
@ Clément "Ketika topdown adalah Benar, penelepon dapat mengubah daftar dirnames di tempat (mungkin menggunakan del atau slice assignment), dan walk () hanya akan muncul kembali ke subdirektori yang namanya tetap dirnames; ini dapat digunakan untuk memangkas mencari, memaksakan urutan kunjungan tertentu, atau bahkan untuk memberi tahu walk () tentang direktori yang dibuat atau diganti namanya oleh penelepon sebelum melanjutkan walk () lagi. " dari docs.python.org/2/library/os.html#os.walk
bugloaf

Cara paling sederhana untuk mengabaikan beberapa direktori adalah dengan tidak menambahkannya ke nama penggunafor subdirname in dirnames: if subdirname != '.git'
smci

537

Kamu bisa menggunakan

os.listdir(path)

Untuk referensi dan lebih banyak fungsi os, lihat di sini:


1
baik pertanyaan awal hanya cukup samar untuk tidak tahu apakah mereka menginginkan solusi rekursif. "semua file dalam direktori" dapat diartikan sebagai rekursif.
Tommy

3
@Tommy, "direktori" adalah struktur data yang didefinisikan dengan jelas, dan mengacu pada "ls" daripada "ls -R". Selain itu, hampir semua alat UNIX tidak bekerja secara rekursif secara default. Saya tidak tahu apa artinya si penanya, tetapi apa yang ditulisnya jelas.
Torsten Bronger

Python 3 docs meminta Anda untuk menggunakannya os.scandirsebagai gantinya, karena dalam banyak kasus itu memungkinkan Anda untuk mencegah panggilan sistem, memberikan speedup gratis (baik IPC dan IO lambat).
Jappie Kerk

5
listdir memberi Anda satu-satunya nama file dalam direktori, apakah ada metode yang tersedia untuk mendapatkan path lengkap?
greperror

1
@ greperror Anda dapat menggunakan os.path.abspath untuk mendapatkan path lengkap. Juga, untuk memeriksa apakah path yang diberikan adalah file, gunakan os.path.isfile atau os.path.isdir.
Aleksandar

111

Inilah fungsi pembantu yang sering saya gunakan:

import os

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

3
Generator akan lebih baik.
Robert Siemer

1
@RobertSiemer tergantung pada penggunaan. Dalam banyak kasus, daftar akan lebih baik, tetapi saya kira generator lebih fleksibel karena dapat dikonversi ke daftar. Itu tergantung pada apakah Anda mencari, keserbagunaan atau sesuatu yang sedikit lebih ramping.
James Mchugh

3
Sudah sepuluh tahun, tapi saya pikir saya melakukannya dengan cara ini karena os.listdir () mengembalikan daftar dan saya meniru itu.
giltay

82
import os

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

16
r'C:\temp'lebih jelas dan lebih disukai daripada "C:\\temp"Rawstrings lebih disukai daripada escaling backslash.
smci

13

Jika Anda membutuhkan kemampuan menggumpal, ada modul untuk itu juga. Sebagai contoh:

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

akan mengembalikan sesuatu seperti:

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

Lihat dokumentasi di sini .


10

Coba ini:

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

Dalam satu baris: [atas + os.sep + f untuk atas, dirs, file di os.walk ('./') untuk f dalam file]
J. Peterson

9

Untuk file dalam direktori kerja saat ini tanpa menentukan path

Python 2.7:

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

Python 3.x:

import os
os.listdir()

Terima kasih kepada Stam Kaly untuk komentar tentang python 3.x


5
os.listdir()daftar elemen dalam direktori saat ini secara default! Jadi tidak perlu untuk os.getcwd():)
Stam Kaly

Bagaimana saya melakukan ini? Ketika saya menggunakan >>> os.listdir () tanpa argumen saya mendapatkan: TypeError: listdir () mengambil tepat 1 argumen (0 diberikan)
Dave Engineer

2
Saya menganggap Anda menjalankan pada 2.7. Ini ditambahkan pada 3.x
Stam Kaly

5

Implementasi rekursif

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

Saya menulis versi panjang, dengan semua opsi yang mungkin saya butuhkan: http://sam.nipl.net/code/python/find.py

Saya kira itu akan cocok di sini juga:

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

Ini pilihan lain.

os.scandir(path='.')

Ini mengembalikan sebuah iterator dari objek os.DirEntry yang sesuai dengan entri (bersama dengan informasi atribut file) di direktori yang diberikan oleh path.

Contoh:

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

Menggunakan scandir () sebagai ganti listdir () dapat secara signifikan meningkatkan kinerja kode yang juga memerlukan tipe file atau informasi atribut file , karena objek os.DirEntry memaparkan informasi ini jika sistem operasi menyediakannya ketika memindai direktori. Semua metode os.DirEntry dapat melakukan panggilan sistem, tetapi is_dir () dan is_file () biasanya hanya memerlukan panggilan sistem untuk tautan simbolik; os.DirEntry.stat () selalu membutuhkan panggilan sistem di Unix tetapi hanya membutuhkan satu untuk tautan simbolis pada Windows.

Python Documents


3

Meskipun os.listdir()baik-baik saja untuk membuat daftar nama file dan dir, sering kali Anda ingin melakukan lebih banyak setelah Anda memiliki nama-nama itu - dan dengan Python3, pathlib membuat tugas-tugas lainnya menjadi sederhana. Mari kita lihat dan lihat apakah Anda menyukainya sama seperti saya.

Untuk daftar isi dir, buat objek Path dan ambil iterator:

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

Jika kita ingin daftar nama saja:

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

Jika Anda hanya menginginkan dir:

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

Jika Anda ingin nama semua file conf di pohon itu:

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

Jika Anda ingin daftar file conf di pohon> = 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',

Menyelesaikan jalur relatif menjadi mudah:

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

Menavigasi dengan Path cukup jelas (meskipun tidak terduga):

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

Satu liner yang bagus untuk daftar hanya file secara rekursif. Saya menggunakan ini di directive setup.py package_data saya:

import os

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

Saya tahu itu bukan jawaban untuk pertanyaan itu, tetapi mungkin berguna


1

Untuk Python 2

#!/bin/python2

import os

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

Untuk Python 3

Untuk memfilter dan memetakan, Anda perlu membungkusnya dengan daftar ()

#!/bin/python3

import os

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

Rekomendasi sekarang adalah Anda mengganti penggunaan peta dan filter Anda dengan ekspresi generator atau pemahaman daftar:

#!/bin/python

import os

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

1

Ini adalah versi Pythonic satu baris:

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

Kode ini mencantumkan path lengkap semua file dan direktori dalam nama direktori yang diberikan.


Terima kasih Saleh, tetapi kode Anda tidak berfungsi sepenuhnya, dan yang berfungsi dimodifikasi sebagai berikut: 'dir =' given_directory_name 'filenames = [os.path.abspath (os.path.join (dir, i)) untuk saya di os.listdir (dir)] '
HassanSh__3571619

1

Saya tahu ini adalah pertanyaan lama. Ini adalah cara yang rapi yang saya temui jika Anda menggunakan mesin 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
Pertanyaan ini sudah memiliki jawaban yang sangat bagus, tidak perlu dijawab lagi
Mike Pennington

0

FYI Tambahkan filter ekstensi atau os file impor ext

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

Jika saya pikir saya akan memasukkan ini. Cara sederhana dan kotor untuk melakukan pencarian wildcard.

import re
import os

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

0

Kode di bawah ini akan mencantumkan direktori dan file dalam direktori

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

Yang bekerja dengan saya adalah jenis versi modifikasi dari jawaban Saleh di atas.

Kode tersebut adalah sebagai berikut:

"dir = 'given_directory_name' filenames = [os.path.abspath (os.path.join (dir, i)) untuk saya di os.listdir (dir)]"

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.