Saya memiliki latar belakang C ++ / Obj-C dan saya baru saja menemukan Python (telah menulisnya sekitar satu jam). Saya sedang menulis skrip untuk secara rekursif membaca isi file teks dalam struktur folder.
Masalah yang saya miliki adalah kode yang saya tulis hanya akan berfungsi untuk satu folder. Saya bisa melihat mengapa dalam kode (lihat #hardcoded path
), saya hanya tidak tahu bagaimana saya bisa bergerak maju dengan Python karena pengalaman saya dengan itu hanya baru.
Kode Python:
import os
import sys
rootdir = sys.argv[1]
for root, subFolders, files in os.walk(rootdir):
for folder in subFolders:
outfileName = rootdir + "/" + folder + "/py-outfile.txt" # hardcoded path
folderOut = open( outfileName, 'w' )
print "outfileName is " + outfileName
for file in files:
filePath = rootdir + '/' + file
f = open( filePath, 'r' )
toWrite = f.read()
print "Writing '" + toWrite + "' to" + filePath
folderOut.write( toWrite )
f.close()
folderOut.close()
os.walk
tidak buruk, meskipun saya datang dengan cara yang lebih cepatos.scandir
. Semuaglob
solusi jauh lebih lambat daripadawalk
&scandir
. Fungsi saya, serta analisis kecepatan lengkap, dapat ditemukan di sini: stackoverflow.com/a/59803793/2441026Jika Anda menggunakan Python 3.5 atau lebih tinggi, Anda bisa menyelesaikannya dalam 1 baris.
Seperti disebutkan dalam dokumentasi
Jika Anda ingin setiap file, Anda dapat menggunakan
sumber
root_dir
membutuhkan garis miring? Ini akan menghemat waktu orang (atau setidaknya itu akan menghemat waktu saya). Terima kasih.glob.iglob(root_dir + '**/**', recursive=True)
. Saya bekerja di Python 3.8.2Setuju dengan Dave Webb,
os.walk
akan menghasilkan item untuk setiap direktori di pohon. Faktanya adalah, Anda tidak perlu pedulisubFolders
.Kode seperti ini seharusnya berfungsi:
sumber
TL; DR: Ini sama dengan
find -type f
untuk memeriksa semua file di semua folder di bawah ini dan termasuk yang sekarang:Seperti yang sudah disebutkan dalam jawaban lain,
os.walk()
adalah jawabannya, tetapi bisa dijelaskan lebih baik. Sederhana saja! Mari kita berjalan melalui pohon ini:Dengan kode ini:
Ini
currentpath
adalah folder yang sedang dilihatnya. Ini akan menampilkan:Jadi loop tiga kali, karena ada tiga folder: yang sekarang
docs
,, danpics
. Di setiap loop, ia mengisi variabelfolders
danfiles
dengan semua folder dan file. Mari kita tunjukkan pada mereka:Ini menunjukkan kepada kita:
Jadi di baris pertama, kita melihat bahwa kita berada di folder
.
, yang berisi dua folder yaitupics
dandocs
, dan bahwa ada satu file, yaitutodo.txt
. Anda tidak perlu melakukan apa pun untuk berulang ke folder itu, karena seperti yang Anda lihat, itu berulang secara otomatis dan hanya memberi Anda file dalam subfolder. Dan subfolder apa pun dari itu (meskipun kami tidak memiliki mereka dalam contoh).Jika Anda hanya ingin mengulang semua file, yang setara dengan
find -type f
, Anda dapat melakukan ini:Output ini:
sumber
The
pathlib
perpustakaan benar-benar hebat untuk bekerja dengan file. Anda dapat melakukan gumpalan rekursif padaPath
objek seperti itu.sumber
Jika Anda ingin daftar datar semua jalur di bawah direktori tertentu (seperti
find .
di shell):Untuk hanya menyertakan path lengkap ke file di bawah dir base, tinggalkan
+ subdirs
.sumber
**/**
digunakan untuk mendapatkan semua file secara rekursif termasukdirectory
.if os.path.isfile(filename)
digunakan untuk memeriksa apakahfilename
variabel adalahfile
ataudirectory
, apakah itu file maka kita dapat membaca file itu. Di sini saya mencetak file.sumber
Saya menemukan yang berikut ini sebagai yang termudah
Menggunakan
glob('some/path/**', recursive=True)
mendapat semua file, tetapi juga termasuk nama direktori. Menambahkanif os.path.isfile(f)
kondisi ini memfilter daftar ini hanya untuk file yang adasumber
gunakan
os.path.join()
untuk membangun jalur Anda - Lebih rapi:sumber
os.walk
tidak berjalan rekursif secara default. Untuk setiap dir, mulai dari root menghasilkan 3-tupel (dirpath, dirnames, nama file)sumber
walk()
jangan kembali daftar rekursif. Saya mencoba kode Anda dan mendapat daftar dengan banyak pengulangan ... Jika Anda hanya menghapus baris di bawah komentar "# panggilan rekursif pada subfolder" - berfungsi dengan baikCoba ini:
sumber
Saya pikir masalahnya adalah Anda tidak memproses output
os.walk
dengan benar.Pertama, ubah:
untuk:
rootdir
adalah direktori awal tetap Anda;root
adalah direktori yang dikembalikan olehos.walk
.Kedua, Anda tidak perlu membuat indentasi loop pemrosesan file Anda, karena tidak masuk akal untuk menjalankan ini untuk setiap subdirektori. Anda akan
root
diatur ke setiap subdirektori. Anda tidak perlu memproses subdirektori dengan tangan kecuali jika Anda ingin melakukan sesuatu dengan direktori itu sendiri.sumber
filePath = rootdir + '/' + file
, itu kedengarannya tidak benar: file berasal dari daftar file saat ini, jadi Anda menulis ke banyak file yang ada?