Iterasi melalui direktori dengan Python


158

Saya perlu mengulang melalui subdirektori dari direktori yang diberikan dan mencari file. Jika saya mendapatkan file saya harus membukanya dan mengubah konten dan menggantinya dengan baris saya sendiri.

Saya mencoba ini:

import os

rootdir ='C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        f=open(file,'r')
        lines=f.readlines()
        f.close()
        f=open(file,'w')
        for line in lines:
            newline = "No you are not"
            f.write(newline)
        f.close()

tapi saya mendapatkan kesalahan. Apa yang saya lakukan salah?


12
"An error" - ada kesalahan khususnya?
Daniel Roseman

1
Tolong bisakah Anda menjelaskan sedikit tentang apa yang Anda harap akan dilakukan dengan file / direktori begitu Anda berhasil menggunakannya? Harap berikan detail kesalahan.
ChrisProsser

1
Pesan kesalahan yang saya dapatkan adalah bahwa file cool.txt tidak ditemukan. Di folder pengujian saya, saya punya folder lain bernama src dan di folder src saya punya folder lain yang disebut main, di folder ini saya punya cool.txt
Wolf

4
bisakah Anda menulis kesalahan dalam pertanyaan? itu menjengkelkan dan tidak perlu harus membaca komentar untuk menemukannya.
Charlie Parker

1
lebih dari setahun kemudian saya tidak percaya saya kembali meminta kesalahan untuk diposting? @ Wolf
Charlie Parker

Jawaban:


301

Berjalan aktual melalui direktori berfungsi seperti yang Anda lakukan. Jika Anda mengganti konten loop dalam dengan printpernyataan sederhana, Anda dapat melihat bahwa setiap file ditemukan:

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print os.path.join(subdir, file)

Jika Anda masih mendapatkan kesalahan saat menjalankan di atas, berikan pesan kesalahan.


Diperbarui untuk Python3

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print(os.path.join(subdir, file))

1
C: / Pengguna / sid / Desktop / test \ src \ app / cool.txt C: / Users / sid / Desktop / test \ src \ app / woohoo.txt Ya dalam pernyataan terbuka kode saya, saya pikir saya harus berikan path absolut ke file. import os rootdir = 'C: / Pengguna / spemmara / Desktop / test / src / app /' untuk subdir, dirs, file di os.walk (rootdir): untuk file dalam file: f = buka (subdir + '/' + file , 'r') lines = f.readlines () f.close () f = buka (subdir + '/' + file, 'w') untuk baris-baris: baris baru = "hey i know" f.write (baris baru) f.close () Terima kasih kawan. Dipecahkan
Wolf

3
Hai! Harap diingat bahwa "print" di python 3 memerlukan tanda kurung, jika tidak, kembalikan kesalahan sintaksis. Semoga ini membantu!
Tommaso Di Noto

14

Cara lain untuk kembali semua file dalam subdirektori adalah dengan menggunakan satu pathlibmodul , diperkenalkan di Python 3.4, yang menyediakan pendekatan berorientasi objek untuk penanganan jalur filesystem (Pathlib juga tersedia di Python 2.7 melalui modul pathlib2 pada PyPI ):

from pathlib import Path

rootdir = Path('C:/Users/sid/Desktop/test')
# Return a list of regular files only, not directories
file_list = [f for f in rootdir.glob('**/*') if f.is_file()]

# For absolute paths instead of relative the current dir
file_list = [f for f in rootdir.resolve().glob('**/*') if f.is_file()]

Sejak Python 3.5, globmodul ini juga mendukung pencarian file rekursif:

import os
from glob import iglob

rootdir_glob = 'C:/Users/sid/Desktop/test/**/*' # Note the added asterisks
# This will return absolute paths
file_list = [f for f in iglob('**/*', recursive=True) if os.path.isfile(f)]

Itu file_list salah satu dari pendekatan di atas dapat diulangi tanpa perlu loop bersarang:

for f in file_list:
    print(f) # Replace with desired operations

1
Apa yang lebih disukai di sini untuk Python 3.6?
PhoenixDev

@PhoenixDev Saya belum pernah mendengar satu pendekatan yang direkomendasikan dari yang lain secara umum. Saya lebih suka menggunakan pathlibdiri saya sendiri, terutama karena saya suka metode-sintaks berorientasi objek. Ada perbedaan lain, seperti pustaka jalur mengembalikan kelas jalur khusus daripada string, dan fungsi yang tersedia berbeda antara pustaka (misalnya os.path.expanduser('~')vs Path.home()). Jelajahi dokumentasi dan lihat pendekatan mana yang Anda inginkan.
joelostblom

Alih-alih menambahkan **dalam pola glob, Anda bisa menggunakan rglob.
Georgy

12

Pada tahun 2020 , glob.iglob(path/**, recursive=True)tampaknya solusi yang paling pythonic , yaitu:

import glob, os

for filename in glob.iglob('/pardadox-music/**', recursive=True):
    if os.path.isfile(filename): # filter dirs
        print(filename)

Keluaran:

/pardadox-music/modules/her1.mod
/pardadox-music/modules/her2.mod
...

Catatan:
1 - glob.iglob

glob.iglob(pathname, recursive=False)

Kembalikan iterator yang menghasilkan nilai yang sama dengan glob() tanpa benar-benar menyimpan semuanya secara bersamaan.

2 - Jika rekursif adalah True, pola '**'akan cocok dengan file apa pun dan nol atau lebihdirectories dan subdirectories.

3 - Jika direktori berisi file yang dimulai dengan  .mereka tidak akan dicocokkan secara default. Misalnya, pertimbangkan direktori yang berisi  card.gif dan .card.gif:

>>> import glob
>>> glob.glob('*.gif') ['card.gif'] 
>>> glob.glob('.c*')['.card.gif']

4 - Anda juga dapat menggunakan rglob(pattern), yang sama dengan menelepon  glob() dengan **/menambahkan di depan pola relatif yang diberikan.


1
Ini pythonic solusi tidak daftar file yang tersembunyi (alias dotfiles) sedangkan yang diterima tidak.
ashrasmun

@ashrasmun Apa yang Anda sebutkan dijelaskan dengan baik di docs.python.org/3/library/glob.html
CONvid19
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.