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.

thomytheyon
sumber

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.

Eli Bendersky
sumber
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)
Ivan
sumber
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('/')]
ThorSummoner
sumber
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]
Mong H. Ng
sumber
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)
devsaw
sumber
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)])
Daniel
sumber
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)

Genangan air
sumber