Direktori daftar Python, subdirektori, dan file


130

Saya mencoba membuat skrip untuk mencantumkan semua direktori, subdirektori, dan file dalam direktori tertentu.
Saya mencoba ini:

import sys,os

root = "/home/patate/directory/"
path = os.path.join(root, "targetdirectory")

for r,d,f in os.walk(path):
    for file in f:
        print os.path.join(root,file)

Sayangnya itu tidak berfungsi dengan baik.
Saya mendapatkan semua file, tetapi bukan jalur lengkapnya.

Misalnya jika dir struct adalah:

/home/patate/directory/targetdirectory/123/456/789/file.txt

Ini akan mencetak:

/home/patate/directory/targetdirectory/file.txt

Yang saya butuhkan adalah hasil pertama. Bantuan apa pun akan sangat dihargai! Terima kasih.

Jawaban:


225

Gunakan os.path.joinuntuk menggabungkan direktori dan nama file :

for path, subdirs, files in os.walk(root):
    for name in files:
        print os.path.join(path, name)

Perhatikan penggunaan pathdan bukan rootdalam penggabungan, karena penggunaan rootakan salah.


Di Python 3.4, modul pathlib ditambahkan untuk manipulasi jalur yang lebih mudah. Jadi setara dengan os.path.join:

pathlib.PurePath(path, name)

Keuntungannya pathlibadalah Anda dapat menggunakan berbagai metode yang berguna di jalur. Jika Anda menggunakan Pathvarian konkret, Anda juga dapat melakukan panggilan OS yang sebenarnya melaluinya, seperti mengubah ke direktori, menghapus jalur, membuka file yang dituju, dan banyak lagi.


ini adalah satu-satunya jawaban yang berguna untuk banyak pertanyaan yang telah ditanyakan tentang "bagaimana mendapatkan semua file secara rekursif dengan python".
harrisonfooord

daftar pemahaman: all_files = [os.path.join (path, name) untuk nama di file untuk path, subdirs, file di os.walk (folder)]
Nir

Dalam Python3 gunakan tanda kurung untuk fungsi cetakprint(os.path.join(path, name))
Ehsan

45

Untuk berjaga-jaga ... Mendapatkan semua file di direktori dan subdirektori yang cocok dengan beberapa pola (* .py misalnya):

import os
from fnmatch import fnmatch

root = '/some/directory'
pattern = "*.py"

for path, subdirs, files in os.walk(root):
    for name in files:
        if fnmatch(name, pattern):
            print os.path.join(path, name)

10

Ini satu baris:

import os

[val for sublist in [[os.path.join(i[0], j) for j in i[2]] for i in os.walk('./')] for val in sublist]
# Meta comment to ease selecting text

Pengulangan paling luar val for sublist in ...meratakan daftar menjadi satu dimensi. The jLoop mengumpulkan daftar setiap file basename dan bergabung ke jalan saat ini. Terakhir, iloop mengulang semua direktori dan sub direktori.

Contoh ini menggunakan jalur hard-code ./dalam os.walk(...)panggilan, Anda dapat menambahkan string jalur apa pun yang Anda suka.

Catatan: os.path.expanduserdan / atau os.path.expandvarsdapat digunakan untuk string jalur seperti~/

Memperluas contoh ini:

Sangat mudah untuk menambahkan tes nama dasar file dan tes nama direktori.

Sebagai Contoh, menguji *.jpgfile:

... for j in i[2] if j.endswith('.jpg')] ...

Selain itu, tidak termasuk .gitdirektori:

... for i in os.walk('./') if '.git' not in i[0].split('/')]

Itu berhasil, tetapi untuk mengeluarkan .git directoy Anda perlu memeriksa apakah '.git' TIDAK masuk ke jalur.
Roman Rdgz

Ya. Harus jika '.git' tidak dalam i [0] .split ('/')]
Roman Rdgz

Saya akan merekomendasikan os.walkmelalui loop dirlisting manual, generator sangat bagus, gunakan saja.
ThorSummoner

9

Tidak bisa berkomentar jadi menulis jawaban di sini. Ini adalah satu baris paling jelas yang pernah saya lihat:

import os
[os.path.join(path, name) for path, subdirs, files in os.walk(root) for name in files]

4

Anda dapat melihat sampel yang saya buat ini. Ia menggunakan fungsi os.path.walk yang sudah usang, berhati-hatilah. Menggunakan daftar untuk menyimpan semua jalur file

root = "Your root directory"
ex = ".txt"
where_to = "Wherever you wanna write your file to"
def fileWalker(ext,dirname,names):
    '''
    checks files in names'''
    pat = "*" + ext[0]
    for f in names:
        if fnmatch.fnmatch(f,pat):
            ext[1].append(os.path.join(dirname,f))


def writeTo(fList):

    with open(where_to,"w") as f:
        for di_r in fList:
            f.write(di_r + "\n")






if __name__ == '__main__':
    li = []
    os.path.walk(root,fileWalker,[ex,li])

    writeTo(li)

4

Satu baris yang sedikit lebih sederhana:

import os
from itertools import product, chain

chain.from_iterable([[os.sep.join(w) for w in product([i[0]], i[2])] for i in os.walk(dir)])

2

Karena setiap contoh di sini hanya menggunakan walk(dengan join), saya ingin menunjukkan contoh yang bagus dan perbandingan dengan listdir:

import os, time

def listFiles1(root): # listdir
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0)+"/"; items = os.listdir(folder) # items = folders + files
        for i in items: i=folder+i; (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles2(root): # listdir/join (takes ~1.4x as long) (and uses '\\' instead)
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0); items = os.listdir(folder) # items = folders + files
        for i in items: i=os.path.join(folder,i); (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles3(root): # walk (takes ~1.5x as long)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[folder.replace("\\","/")+"/"+file] # folder+"\\"+file still ~1.5x
    return allFiles

def listFiles4(root): # walk/join (takes ~1.6x as long) (and uses '\\' instead)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[os.path.join(folder,file)]
    return allFiles


for i in range(100): files = listFiles1("src") # warm up

start = time.time()
for i in range(100): files = listFiles1("src") # listdir
print("Time taken: %.2fs"%(time.time()-start)) # 0.28s

start = time.time()
for i in range(100): files = listFiles2("src") # listdir and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.38s

start = time.time()
for i in range(100): files = listFiles3("src") # walk
print("Time taken: %.2fs"%(time.time()-start)) # 0.42s

start = time.time()
for i in range(100): files = listFiles4("src") # walk and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.47s

Jadi seperti yang Anda lihat sendiri, listdirversinya jauh lebih efisien. (dan itu joinlambat)

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.