os.listdir()akan memberi Anda semua yang ada di direktori - file dan direktori .
Jika Anda hanya ingin file, Anda bisa memfilter ini menggunakan os.path:
from os import listdir
from os.path import isfile, join
onlyfiles =[f for f in listdir(mypath)if isfile(join(mypath, f))]
atau Anda bisa menggunakan os.walk()yang akan menghasilkan dua daftar untuk setiap direktori yang dikunjungi - membaginya menjadi file dan dir untuk Anda. Jika Anda hanya menginginkan direktori teratas, Anda bisa memecahnya saat pertama kali menghasilkan
from os import walk
f =[]for(dirpath, dirnames, filenames)in walk(mypath):
f.extend(filenames)break
Sedikit lebih sederhana: (_, _, filenames) = walk(mypath).next() (jika Anda yakin bahwa jalan akan mengembalikan setidaknya satu nilai, yang seharusnya.)
misterbee
9
Sedikit modifikasi untuk menyimpan path lengkap: untuk (dirpath, dirnames, nama file) di os.walk (mypath): checksum_files.extend (os.path.join (dirpath, nama file) untuk nama file dalam nama file) break
okigan
150
f.extend(filenames)sebenarnya tidak sama dengan f = f + filenames. extendakan memodifikasi fdi tempat, sedangkan menambahkan membuat daftar baru di lokasi memori baru. Ini berarti extendumumnya lebih efisien daripada +, tetapi kadang-kadang dapat menyebabkan kebingungan jika beberapa objek menyimpan referensi ke daftar. Terakhir, perlu dicatat bahwa f += filenamesitu setara dengan f.extend(filenames), bukanf = f + filenames .
Benjamin Hodgson
30
@ maisterbee, solusi Anda adalah yang terbaik, hanya satu perbaikan kecil:_, _, filenames = next(walk(mypath), (None, None, []))
bgusach
35
dalam penggunaan python 3.x(_, _, filenames) = next(os.walk(mypath))
ET-CS
1683
Saya lebih suka menggunakan globmodul, seperti halnya pencocokan pola dan ekspansi.
import glob
print(glob.glob("/home/adam/*.txt"))
Ini akan mengembalikan daftar dengan file yang diminta:
untuk memperjelas, ini tidak mengembalikan "path lengkap"; ia hanya mengembalikan ekspansi gumpal, apa pun itu. Misalnya, diberikan /home/user/foo/bar/hello.txt, maka, jika berjalan di direktori foo, glob("bar/*.txt")akan kembali bar/hello.txt. Ada beberapa kasus ketika Anda benar-benar menginginkan jalur penuh (yaitu absolut); untuk kasus-kasus tersebut, lihat stackoverflow.com/questions/51520/…
tidak menjawab pertanyaan ini. glob.glob("*")akan.
Jean-François Fabre
Cantik!!!! jadi .... x=glob.glob("../train/*.png")akan memberi saya array jalur saya, selama saya tahu nama foldernya. Keren abis!
Jennifer Crosby
860
Dapatkan daftar file dengan Python 2 dan 3
os.listdir()
Cara mendapatkan semua file (dan direktori) di direktori saat ini (Python 3)
Berikut ini, adalah metode sederhana untuk mengambil hanya file di direktori saat ini, menggunakan os dan listdir()fungsinya, dalam Python 3. Eksplorasi lebih lanjut, akan menunjukkan cara mengembalikan folder di direktori, tetapi Anda tidak akan memiliki file di subdirektori, untuk itu Anda bisa menggunakan jalan - bahas nanti).
import os
arr = os.listdir()print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
glob
Saya menemukan glob lebih mudah untuk memilih file dengan tipe yang sama atau dengan sesuatu yang sama. Lihatlah contoh berikut:
import glob
txtfiles =[]for file in glob.glob("*.txt"):
txtfiles.append(file)
glob dengan pemahaman daftar
import glob
mylist =[f for f in glob.glob("*.txt")]
glob dengan suatu fungsi
Fungsi mengembalikan daftar ekstensi yang diberikan (.txt, .docx ecc.) Dalam argumen
import glob
def filebrowser(ext=""):"Returns files with an extension"return[f for f in glob.glob(f"*{ext}")]
x = filebrowser(".txt")print(x)>>>['example.txt','fb.txt','intro.txt','help.txt']
glob memperpanjang kode sebelumnya
Fungsi sekarang mengembalikan daftar file yang cocok dengan string yang Anda berikan sebagai argumen
import glob
def filesearch(word=""):"""Returns a list with all files with the word/extension in it"""
file =[]for f in glob.glob("*"):if word[0]==".":if f.endswith(word):
file.append(f)return file
elif word in f:
file.append(f)return file
return file
lookfor ="example",".py"for w in lookfor:print(f"{w:10} found => {filesearch(w)}")
keluaran
example found =>[].py found =>['search.py']
Mendapatkan nama jalur lengkap dengan os.path.abspath
Seperti yang Anda perhatikan, Anda tidak memiliki path lengkap file dalam kode di atas. Jika Anda perlu memiliki path absolut, Anda dapat menggunakan fungsi lain dari os.pathmodul yang disebut _getfullpathname, menempatkan file yang Anda dapatkan os.listdir()sebagai argumen. Ada cara lain untuk memiliki path lengkap, seperti yang akan kita periksa nanti (saya ganti, seperti yang disarankan oleh mexmex, dengan _getfullpathname abspath).
import os
files_path =[os.path.abspath(x)for x in os.listdir()]print(files_path)>>>['F:\\documenti\applications.txt','F:\\documenti\collections.txt']
Dapatkan nama path lengkap dari jenis file ke semua subdirektori dengan walk
Saya menemukan ini sangat berguna untuk menemukan barang di banyak direktori, dan itu membantu saya menemukan file yang saya tidak ingat namanya:
import os
# Getting the current work directory (cwd)
thisdir = os.getcwd()# r=root, d=directories, f = filesfor r, d, f in os.walk(thisdir):for file in f:if file.endswith(".docx"):print(os.path.join(r, file))
os.listdir(): dapatkan file di direktori saat ini (Python 2)
Dalam Python 2, jika Anda ingin daftar file di direktori saat ini, Anda harus memberikan argumen sebagai '.' atau os.getcwd () dalam metode os.listdir.
import os
arr = os.listdir('.')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Untuk naik di pohon direktori
# Method 1
x = os.listdir('..')# Method 2
x= os.listdir('/')
Dapatkan file: os.listdir()di direktori tertentu (Python 2 dan 3)
import os
arr = os.listdir('F:\\python')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Dapatkan file dari subdirektori tertentu dengan os.listdir()
import os
x = os.listdir("./content")
os.walk('.') - direktori saat ini
import os
arr = next(os.walk('.'))[2]print(arr)>>>['5bs_Turismo1.pdf','5bs_Turismo1.pptx','esperienza.txt']
next(os.walk('.')) dan os.path.join('dir', 'file')
import os
arr =[]for d,r,f in next(os.walk("F:\\_python")):for file in f:
arr.append(os.path.join(r,file))for f in arr:print(files)>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt
next(os.walk('F:\\') - dapatkan path lengkap - daftar pemahaman
[os.path.join(r,file)for r,d,f in next(os.walk("F:\\_python"))for file in f]>>>['F:\\_python\\dict_class.py','F:\\_python\\programmi.txt']
os.walk - dapatkan path lengkap - semua file dalam subdirektori **
x =[os.path.join(r,file)for r,d,f in os.walk("F:\\_python")for file in f]print(x)>>>['F:\\_python\\dict.py','F:\\_python\\progr.txt','F:\\_python\\readl.py']
os.listdir() - dapatkan hanya file txt
arr_txt =[x for x in os.listdir()if x.endswith(".txt")]print(arr_txt)>>>['work.txt','3ebooks.txt']
Menggunakan globuntuk mendapatkan path lengkap file
Jika saya perlu path absolut dari file:
from path import path
from glob import glob
x =[path(f).abspath()for f in glob("F:\\*.txt")]for f in x:print(f)>>> F:\acquistionline.txt
>>> F:\acquisti_2018.txt
>>> F:\bootstrap_jquery_ecc.txt
Menggunakan os.path.isfileuntuk menghindari direktori dalam daftar
import os.path
listOfFiles =[f for f in os.listdir()if os.path.isfile(f)]print(listOfFiles)>>>['a simple game.py','data.txt','decorator.py']
Menggunakan pathlibdari Python 3.4
import pathlib
flist =[]for p in pathlib.Path('.').iterdir():if p.is_file():print(p)
flist.append(p)>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speak_gui2.py
>>> thumb.PNG
Dengan list comprehension:
flist =[p for p in pathlib.Path('.').iterdir()if p.is_file()]
import os
x =[i[2]for i in os.walk('.')]
y=[]for t in x:for f in t:
y.append(f)print(y)>>>['append_to_list.py','data.txt','data1.txt','data2.txt','data_180617','os_walk.py','READ2.py','read_data.py','somma_defaltdic.py','substitute_words.py','sum_data.py','data.txt','data1.txt','data_180617']
Dapatkan hanya file dengan langkah berikutnya dan berjalan di direktori
import os
x = next(os.walk('F://python'))[2]print(x)>>>['calculator.bat','calculator.py']
Dapatkan hanya direktori dengan yang berikutnya dan berjalan di direktori
import os
next(os.walk('F://python'))[1]# for the current dir use ('.')>>>['python3','others']
Dapatkan semua nama subdir walk
for r,d,f in os.walk("F:\\_python"):for dirs in d:print(dirs)>>>.vscode
>>> pyexcel
>>> pyschool.py
>>> subtitles
>>> _metaprogramming
>>>.ipynb_checkpoints
os.scandir() dari Python 3.5 dan lebih tinggi
import os
x =[f.name for f in os.scandir()if f.is_file()]print(x)>>>['calculator.bat','calculator.py']# Another example with scandir (a little variation from docs.python.org)# This one is more efficient than os.listdir.# In this case, it shows the files only in the current directory# where the script is executed.import os
with os.scandir()as i:for entry in i:if entry.is_file():print(entry.name)>>> ebookmaker.py
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speakgui4.py
>>> speak_gui2.py
>>> speak_gui3.py
>>> thumb.PNG
Contoh:
Ex. 1: Berapa banyak file yang ada di subdirektori?
Dalam contoh ini, kami mencari jumlah file yang termasuk dalam semua direktori dan subdirektori.
import os
def count(dir, counter=0):"returns number of files in dir and subdirs"for pack in os.walk(dir):for f in pack[2]:
counter +=1return dir +" : "+ str(counter)+"files"print(count("F:\\python"))>>>'F:\\\python':12057 files'
Contoh.2: Bagaimana cara menyalin semua file dari direktori ke direktori lain?
Sebuah skrip untuk membuat pesanan di komputer Anda menemukan semua file dari jenis (default: pptx) dan menyalinnya di folder baru.
import os
import shutil
from path import path
destination ="F:\\file_copied"# os.makedirs(destination)def copyfile(dir, filetype='pptx', counter=0):"Searches for pptx (or other - pptx is the default) files and copies them"for pack in os.walk(dir):for f in pack[2]:if f.endswith(filetype):
fullpath = pack[0]+"\\"+ f
print(fullpath)
shutil.copy(fullpath, destination)
counter +=1if counter >0:print('-'*30)print("\t==> Found in: `"+ dir +"` : "+ str(counter)+" files\n")for dir in os.listdir():"searches for folders that starts with `_`"if dir[0]=='_':# copyfile(dir, filetype='pdf')
copyfile(dir, filetype='txt')>>> _compiti18\Compito Contabilità1\conti.txt
>>> _compiti18\Compito Contabilità1\modula4.txt
>>> _compiti18\Compito Contabilità1\moduloa4.txt
>>>------------------------>>>==>Foundin:`_compiti18`:3 files
Ex. 3: Cara mendapatkan semua file dalam file txt
Jika Anda ingin membuat file txt dengan semua nama file:
import os
mylist =""with open("filelist.txt","w", encoding="utf-8")as file:for eachfile in os.listdir():
mylist += eachfile +"\n"
file.write(mylist)
Contoh: txt dengan semua file hard drive
"""
We are going to save a txt file with all the files in your directory.
We will use the function walk()
"""import os
# see all the methods of os# print(*dir(os), sep=", ")
listafile =[]
percorso =[]with open("lista_file.txt","w", encoding='utf-8')as testo:for root, dirs, files in os.walk("D:\\"):for file in files:
listafile.append(file)
percorso.append(root +"\\"+ file)
testo.write(file +"\n")
listafile.sort()print("N. of files", len(listafile))with open("lista_file_ordinata.txt","w", encoding="utf-8")as testo_ordinato:for file in listafile:
testo_ordinato.write(file +"\n")with open("percorso.txt","w", encoding="utf-8")as file_percorso:for file in percorso:
file_percorso.write(file +"\n")
os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")
Semua file C: \ dalam satu file teks
Ini adalah versi lebih pendek dari kode sebelumnya. Ubah folder tempat mulai mencari file jika Anda perlu memulai dari posisi lain. Kode ini menghasilkan 50 mb pada file teks di komputer saya dengan sesuatu yang kurang dari 500.000 baris dengan file dengan path lengkap.
import os
with open("file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk("C:\\"):for file in f:
filewrite.write(f"{r + file}\n")
Cara menulis file dengan semua jalur dalam folder jenis
Dengan fungsi ini Anda dapat membuat file txt yang akan memiliki nama jenis file yang Anda cari (mis. Pngfile.txt) dengan semua path lengkap semua file jenis itu. Kadang-kadang bisa bermanfaat, saya pikir.
import os
def searchfiles(extension='.ttf', folder='H:\\'):"Create a txt file with all the file of a type"with open(extension[1:]+"file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
filewrite.write(f"{r + file}\n")# looking for png file (fonts) in the hard disk H:\
searchfiles('.png','H:\\')>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png
(Baru) Temukan semua file dan buka dengan tkinter GUI
Saya hanya ingin menambahkan di 2019 ini aplikasi kecil untuk mencari semua file dalam sebuah dir dan dapat membukanya dengan menggandakan pada nama file dalam daftar.
import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):"insert all files in the listbox"for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
lb.insert(0, r +"\\"+ file)def open_file():
os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png','H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>",lambda x: open_file())
root.mainloop()
Ini adalah mish-mash dari terlalu banyak jawaban untuk pertanyaan yang tidak diajukan di sini. Mungkin juga layak untuk menjelaskan apa peringatan atau pendekatan yang disarankan. Saya tidak lebih baik mengetahui satu cara versus 20 cara untuk melakukan hal yang sama kecuali saya juga tahu mana yang lebih tepat untuk digunakan saat itu.
cs95
Ok, ASAP saya akan melihat jawaban saya dan mencoba membuatnya lebih bersih dan dengan informasi yang lebih berguna tentang perbedaan antara metode dll.
Giovanni G. PY
Anda seharusnya tidak menentukan ekstensi file dengan memeriksa apakah nama file mengandung substring. Itu mungkin menyebabkan banyak masalah. Saya sarankan untuk selalu memeriksa apakah nama file berakhir dengan substring tertentu.
ni1ight
Oke, @ n1light, saya mengubah kode ...
Giovanni G. PY
812
import os
os.listdir("somedirectory")
akan mengembalikan daftar semua file dan direktori di "direktori tertentu".
Ini mengembalikan path relatif file, dibandingkan dengan path lengkap dikembalikan olehglob.glob
xji
22
@ JIXiang: os.listdir()selalu mengembalikan nama file belaka (bukan jalur relatif). Apa yang glob.glob()dikembalikan didorong oleh format jalur dari pola input.
mklement0
os.listdir () -> Selalu daftar direktori dan file di dalam lokasi yang disediakan. Apakah ada cara untuk mendaftar hanya direktori bukan file?
RonyA
160
Solusi satu baris untuk mendapatkan hanya daftar file (tanpa subdirektori):
filenames = next(os.walk(path))[2]
atau nama path absolut:
paths =[os.path.join(path, fn)for fn in next(os.walk(path))[2]]
Hanya satu liner jika Anda sudah melakukannya import os. Tampak kurang ringkas daripada glob()bagi saya.
ArtOfWarfare
4
masalah dengan glob adalah bahwa folder bernama 'something.something' akan dikembalikan oleh glob ('/ home / adam /*.*')
Remi
6
Pada OS X, ada sesuatu yang disebut bundel. Ini adalah direktori yang umumnya harus diperlakukan sebagai file (seperti .tar). Apakah Anda ingin yang diperlakukan sebagai file atau direktori? Menggunakan glob()akan memperlakukannya sebagai file. Metode Anda akan memperlakukannya sebagai direktori.
ArtOfWarfare
132
Mendapatkan Path File Lengkap Dari Direktori dan Semua Subdirektorinya
import os
def get_filepaths(directory):"""
This function will generate the file names in a directory
tree by walking the tree either top-down or bottom-up. For each
directory in the tree rooted at directory top (including top itself),
it yields a 3-tuple (dirpath, dirnames, filenames).
"""
file_paths =[]# List which will store all of the full filepaths.# Walk the tree.for root, directories, files in os.walk(directory):for filename in files:# Join the two strings in order to form the full filepath.
filepath = os.path.join(root, filename)
file_paths.append(filepath)# Add it to the list.return file_paths # Self-explanatory.# Run the above function and store its results in a variable.
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")
Path yang saya berikan pada fungsi di atas berisi 3 file — dua di antaranya di direktori root, dan yang lain di subfolder yang disebut "SUBFOLDER." Anda sekarang dapat melakukan hal-hal seperti:
>>>import pathlib
>>>[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Menurut PEP 428 , tujuan pathlibperpustakaan adalah untuk menyediakan hirarki kelas sederhana untuk menangani jalur sistem file dan operasi umum yang dilakukan pengguna atas mereka.
Terima kasih! Saya pikir ini adalah satu-satunya solusi yang tidak mengembalikan secara langsung a list. Bisa digunakan p.namedaripada yang pertama sebagai palternatif jika lebih disukai.
jeromej
1
Selamat datang! Saya lebih suka membuat pathlib.Path()instance karena mereka memiliki banyak metode yang berguna saya tidak ingin membuang-buang limbah. Anda juga dapat memanggil str(p)mereka untuk nama jalur.
SzieberthAdam
6
Catatan: os.scandirSolusinya akan lebih efisien daripada os.listdirdengan os.path.is_filecek atau sejenisnya, bahkan jika Anda memerlukan list(sehingga Anda tidak mendapat manfaat dari iterasi malas), karena os.scandirmenggunakan API yang disediakan OS yang memberi Anda is_fileinformasi secara gratis karena iterates , tidak ada per-file round trip ke disk untuk statmereka sama sekali (pada Windows, DirEntrys membuat Anda lengkap statinformasi gratis, pada sistem NIX * perlu statuntuk info luar is_file, is_dir, dll, tapi DirEntrycache pada pertama statuntuk kenyamanan).
ShadowRanger
1
Anda juga dapat menggunakan entry.nameuntuk mendapatkan hanya nama file, atau entry.pathuntuk mendapatkan path lengkapnya. Tidak ada lagi os.path.join () di semua tempat.
user136036
56
Catatan awal
Meskipun ada perbedaan yang jelas antara istilah file dan direktori dalam teks pertanyaan, beberapa orang mungkin berpendapat bahwa direktori sebenarnya adalah file khusus
Pernyataan: " semua file direktori " dapat diartikan dalam dua cara:
Semua keturunan langsung (atau level 1) saja
Semua keturunan di seluruh pohon direktori (termasuk yang ada di sub-direktori)
Ketika pertanyaan diajukan, saya membayangkan bahwa Python 2 , adalah versi LTS , namun sampel kode akan dijalankan oleh Python 3 ( .5 ) (saya akan membiarkannya sesuai dengan Python 2 ; mungkin juga, kode apa pun yang dimiliki oleh Python yang akan saya posting, berasal dari v3.5.4 - kecuali ditentukan lain). Itu memiliki konsekuensi yang terkait dengan kata kunci lain dalam pertanyaan: " tambahkan mereka ke dalam daftar ":
Di pra versi Python 2.2 , urutan (iterables) sebagian besar diwakili oleh daftar (tupel, set, ...)
Dalam Python 2.2 , konsep generator ( [Python.Wiki]: Generator ) - milik [Python 3]: Pernyataan hasil ) - diperkenalkan. Seiring berjalannya waktu, generator mulai muncul untuk fungsi-fungsi yang kembali / bekerja dengan daftar
Dalam Python 3 , generator adalah perilaku default
Tidak yakin apakah mengembalikan daftar masih wajib (atau generator juga akan melakukannya), tetapi meneruskan generator ke daftar konstruktor, akan membuat daftar dari daftar itu (dan juga mengkonsumsinya). Contoh di bawah ini mengilustrasikan perbedaan pada [Python 3]: map ( function, iterable, ... )
>>>import sys
>>> sys.version
'2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])# Just a dummy lambda function>>> m, type(m)([1,2,3],<type 'list'>)>>> len(m)3
>>>import sys
>>> sys.version
'3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])>>> m, type(m)(<map object at 0x000001B4257342B0>,<class'map'>)>>> len(m)Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError: object of type 'map' has no len()>>> lm0 = list(m)# Build a list from the generator>>> lm0, type(lm0)([1,2,3],<class'list'>)>>>>>> lm1 = list(m)# Build a list from the same generator>>> lm1, type(lm1)# Empty list now - generator already consumed([],<class'list'>)
Contoh-contoh akan didasarkan pada direktori bernama root_dir dengan struktur berikut (contoh ini untuk Win , tapi saya juga menggunakan pohon yang sama di Lnx ):
Kembali daftar yang berisi nama-nama entri dalam direktori yang diberikan oleh path. Daftar ini dalam urutan acak, dan tidak termasuk entri khusus '.'dan '..'...
>>>import os
>>> root_dir ="root_dir"# Path relative to current dir (os.getcwd())>>>>>> os.listdir(root_dir)# List all the items in root_dir['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[item for item in os.listdir(root_dir)if os.path.isfile(os.path.join(root_dir, item))]# Filter items and only keep files (strip out directories)['file0','file1']
Contoh yang lebih rumit ( code_os_listdir.py ):
import os
from pprint import pformat
def _get_dir_content(path, include_folders, recursive):
entries = os.listdir(path)for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:yield entry_with_path
if recursive:for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):yield sub_entry
else:yield entry_with_path
def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)for item in _get_dir_content(path, include_folders, recursive):yield item if prepend_folder_name else item[path_len:]def _get_dir_content_old(path, include_folders, recursive):
entries = os.listdir(path)
ret = list()for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:
ret.append(entry_with_path)if recursive:
ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))else:
ret.append(entry_with_path)return ret
def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)return[item if prepend_folder_name else item[path_len:]for item in _get_dir_content_old(path, include_folders, recursive)]def main():
root_dir ="root_dir"
ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
lret0 = list(ret0)print(ret0, len(lret0), pformat(lret0))
ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)print(len(ret1), pformat(ret1))if __name__ =="__main__":
main()
Catatan :
Ada dua implementasi:
Yang menggunakan generator (tentu saja di sini sepertinya tidak berguna, karena saya segera mengonversi hasilnya menjadi daftar)
Yang klasik (nama fungsi berakhiran _old )
Rekursi digunakan (untuk masuk ke subdirektori)
Untuk setiap implementasi ada dua fungsi:
Yang dimulai dengan garis bawah ( _ ): "pribadi" (tidak boleh dipanggil secara langsung) - yang melakukan semua pekerjaan
Yang publik (bungkus lebih dari sebelumnya): itu hanya menghapus jalur awal (jika diperlukan) dari entri yang dikembalikan. Ini adalah implementasi yang jelek, tapi itu satu-satunya ide yang bisa saya dapatkan pada saat ini
Dalam hal kinerja, generator umumnya sedikit lebih cepat (mempertimbangkan waktu pembuatan dan iterasi ), tetapi saya tidak mengujinya dalam fungsi rekursif, dan juga saya beralih ke fungsi di dalam generator bagian dalam - tidak tahu bagaimana kinerja ramah itu
Bermainlah dengan argumen untuk mendapatkan hasil yang berbeda
Keluaran :
(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe""code_os_listdir.py"<generator object get_dir_content at 0x000001BDDBB3DF10>22['root_dir\\dir0','root_dir\\dir0\\dir00','root_dir\\dir0\\dir00\\dir000','root_dir\\dir0\\dir00\\dir000\\file0000','root_dir\\dir0\\dir00\\file000','root_dir\\dir0\\dir01','root_dir\\dir0\\dir01\\file010','root_dir\\dir0\\dir01\\file011','root_dir\\dir0\\dir02','root_dir\\dir0\\dir02\\dir020','root_dir\\dir0\\dir02\\dir020\\dir0200','root_dir\\dir1','root_dir\\dir1\\file10','root_dir\\dir1\\file11','root_dir\\dir1\\file12','root_dir\\dir2','root_dir\\dir2\\dir20','root_dir\\dir2\\dir20\\file200','root_dir\\dir2\\file20','root_dir\\dir3','root_dir\\file0','root_dir\\file1']11['dir0\\dir00\\dir000\\file0000','dir0\\dir00\\file000','dir0\\dir01\\file010','dir0\\dir01\\file011','dir1\\file10','dir1\\file11','dir1\\file12','dir2\\dir20\\file200','dir2\\file20','file0','file1']
Mengembalikan iterator objek os.DirEntry yang sesuai dengan entri dalam direktori yang diberikan oleh path . Entri dihasilkan dalam urutan acak, dan entri khusus '.'dan '..'tidak termasuk.
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 memerlukan panggilan sistem di Unix tetapi hanya membutuhkan satu untuk tautan simbolis pada Windows.
>>>import os
>>> root_dir = os.path.join(".","root_dir")# Explicitly prepending current directory>>> root_dir
'.\\root_dir'>>>>>> scandir_iterator = os.scandir(root_dir)>>> scandir_iterator
<nt.ScandirIterator object at 0x00000268CF4BC140>>>>[item.path for item in scandir_iterator]['.\\root_dir\\dir0','.\\root_dir\\dir1','.\\root_dir\\dir2','.\\root_dir\\dir3','.\\root_dir\\file0','.\\root_dir\\file1']>>>>>>[item.path for item in scandir_iterator]# Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)[]>>>>>> scandir_iterator = os.scandir(root_dir)# Reinitialize the generator>>>for item in scandir_iterator :...if os.path.isfile(item.path):...print(item.name)...
file0
file1
Catatan :
Ini mirip dengan os.listdir
Tetapi juga lebih fleksibel (dan menawarkan lebih banyak fungsi), lebih banyak Python ic (dan dalam beberapa kasus, lebih cepat)
Hasilkan nama file di pohon direktori dengan berjalan pohon itu dari atas ke bawah atau dari bawah ke atas. Untuk setiap direktori dalam pohon berakar di direktori atas (termasuk atas sendiri), itu menghasilkan 3-tuple ( dirpath, dirnames, filenames).
>>>import os
>>> root_dir = os.path.join(os.getcwd(),"root_dir")# Specify the full path>>> root_dir
'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'>>>>>> walk_generator = os.walk(root_dir)>>> root_dir_entry = next(walk_generator)# First entry corresponds to the root dir (passed as an argument)>>> root_dir_entry
('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir',['dir0','dir1','dir2','dir3'],['file0','file1'])>>>>>> root_dir_entry[1]+ root_dir_entry[2]# Display dirs and files (direct descendants) in a single list['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(root_dir_entry[0], item)for item in root_dir_entry[1]+ root_dir_entry[2]]# Display all the entries in the previous list by their full path['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']>>>>>>for entry in walk_generator:# Display the rest of the elements (corresponding to every subdir)...print(entry)...('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0',['dir00','dir01','dir02'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00',['dir000'],['file000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000',[],['file0000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01',[],['file010','file011'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02',['dir020'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020',['dir0200'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200',[],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1',[],['file10','file11','file12'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2',['dir20'],['file20'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20',[],['file200'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3',[],[])
Catatan :
Di bawah layar, ia menggunakan os.scandir( os.listdirpada versi yang lebih lama)
Kembalikan daftar nama path yang mungkin kosong yang cocok dengan pathname , yang harus berupa string yang berisi spesifikasi path. pathname bisa berupa absolut (suka /usr/src/Python-1.5/Makefile) atau relatif (suka ../../Tools/*/*.gif), dan dapat berisi wildcard gaya-shell. Symlinks yang rusak termasuk dalam hasil (seperti dalam shell). ... Berubah dalam versi 3.5 : Dukungan untuk gumpalan rekursif menggunakan " **".
>>>import glob, os
>>> wildcard_pattern ="*">>> root_dir = os.path.join("root_dir", wildcard_pattern)# Match every file/dir name>>> root_dir
'root_dir\\*'>>>>>> glob_list = glob.glob(root_dir)>>> glob_list
['root_dir\\dir0','root_dir\\dir1','root_dir\\dir2','root_dir\\dir3','root_dir\\file0','root_dir\\file1']>>>>>>[item.replace("root_dir"+ os.path.sep,"")for item in glob_list]# Strip the dir name and the path separator from begining['dir0','dir1','dir2','dir3','file0','file1']>>>>>>for entry in glob.iglob(root_dir +"*", recursive=True):...print(entry)...
root_dir\
root_dir\dir0
root_dir\dir0\dir00
root_dir\dir0\dir00\dir000
root_dir\dir0\dir00\dir000\file0000
root_dir\dir0\dir00\file000
root_dir\dir0\dir01
root_dir\dir0\dir01\file010
root_dir\dir0\dir01\file011
root_dir\dir0\dir02
root_dir\dir0\dir02\dir020
root_dir\dir0\dir02\dir020\dir0200
root_dir\dir1
root_dir\dir1\file10
root_dir\dir1\file11
root_dir\dir1\file12
root_dir\dir2
root_dir\dir2\dir20
root_dir\dir2\dir20\file200
root_dir\dir2\file20
root_dir\dir3
root_dir\file0
root_dir\file1
Catatan :
Penggunaan os.listdir
Untuk pohon besar (terutama jika rekursif aktif), iglob lebih disukai
Mengizinkan pemfilteran lanjutan berdasarkan nama (karena wildcard)
>>>import pathlib
>>> root_dir ="root_dir">>> root_dir_instance = pathlib.Path(root_dir)>>> root_dir_instance
WindowsPath('root_dir')>>> root_dir_instance.name
'root_dir'>>> root_dir_instance.is_dir()True>>>>>>[item.name for item in root_dir_instance.glob("*")]# Wildcard searching for all direct descendants['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(item.parent.name, item.name)for item in root_dir_instance.glob("*")ifnot item.is_dir()]# Display paths (including parent) for files only['root_dir\\file0','root_dir\\file1']
Catatan :
Ini adalah salah satu cara untuk mencapai tujuan kami
def listdir(path):"""List directory contents, using cache."""try:
cached_mtime, list = cache[path]del cache[path]exceptKeyError:
cached_mtime, list =-1,[]
mtime = os.stat(path).st_mtime
if mtime != cached_mtime:
list = os.listdir(path)
list.sort()
cache[path]= mtime, list
return list
ctypes adalah pustaka fungsi asing untuk Python. Ini menyediakan tipe data yang kompatibel C, dan memungkinkan fungsi panggilan di DLL atau perpustakaan bersama. Ini dapat digunakan untuk membungkus pustaka ini dengan Python murni.
LinuxDirent64 adalah representasi ctypes dari struct dirent64 dari [man7]: dirent.h (0P) (demikian juga konstanta DT_ ) dari mesin saya: Ubtu 16 x64 ( 4.10.0-40-generik dan libc6-dev: amd64 ). Pada rasa / versi lain, definisi struct mungkin berbeda, dan jika demikian, alias ctypes harus diperbarui, jika tidak maka akan menghasilkan Perilaku Tidak Terdefinisi
Ini mengembalikan data dalam os.walkformat. Saya tidak repot untuk membuatnya rekursif, tetapi mulai dari kode yang ada, itu akan menjadi tugas yang cukup sepele
Semuanya bisa dilakukan pada Win juga, data (perpustakaan, fungsi, struct, konstanta, ...) berbeda
Keluaran :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]>./code_ctypes.py
3.5.2(default,Nov122018,13:43:14)[GCC 5.4.020160609] on linux
['root_dir',['dir2','dir1','dir3','dir0'],['file1','file0']]
Mengambil daftar nama file yang cocok, menggunakan Windows Unicode API. Antarmuka ke fungsi FindFirstFileW API / FindNextFileW / Find close.
>>>import os, win32file, win32con
>>> root_dir ="root_dir">>> wildcard ="*">>> root_dir_wildcard = os.path.join(root_dir, wildcard)>>> entry_list = win32file.FindFilesW(root_dir_wildcard)>>> len(entry_list)# Don't display the whole content as it's too long8>>>[entry[-2]for entry in entry_list]# Only display the entry names['.','..','dir0','dir1','dir2','dir3','file0','file1']>>>>>>[entry[-2]for entry in entry_list if entry[0]& win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2]notin(".","..")]# Filter entries and only display dir names (except self and parent)['dir0','dir1','dir2','dir3']>>>>>>[os.path.join(root_dir, entry[-2])for entry in entry_list if entry[0]&(win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]# Only display file "full" names['root_dir\\file0','root_dir\\file1']
Tautan dokumentasi berasal dari ActiveState , karena saya tidak menemukan dokumentasi resmi PyWin32
Instal beberapa (pihak lain) paket pihak ketiga yang melakukan trik
Kemungkinan besar, akan bergantung pada satu (atau lebih) hal di atas (mungkin dengan sedikit penyesuaian)
Catatan :
Kode dimaksudkan untuk portabel (kecuali tempat yang menargetkan area tertentu - yang ditandai) atau tanda silang:
platform ( Nix , Win ,)
Versi python (2, 3,)
Berbagai gaya jalur (absolut, kerabat) digunakan di seluruh varian di atas, untuk menggambarkan fakta bahwa "alat" yang digunakan fleksibel dalam arah ini
_get_dir_content (dari titik # 1. ) dapat diimplementasikan menggunakan salah satu dari pendekatan ini (beberapa akan membutuhkan lebih banyak pekerjaan dan beberapa lagi kurang)
Beberapa pemfilteran tingkat lanjut (alih-alih hanya file vs. dir) dapat dilakukan: misalnya argumen include_folders dapat diganti dengan yang lain (mis. Filter_func ) yang akan menjadi fungsi yang mengambil lintasan sebagai argumen: filter_func=lambda x: True(ini tidak menghapus apapun) dan di dalam _get_dir_content sesuatu seperti: if not filter_func(entry_with_path): continue(jika fungsi gagal untuk satu entri, itu akan dilewati), tetapi semakin kompleks kodenya, semakin lama waktu yang diperlukan untuk mengeksekusi
Nota bene! Karena rekursi digunakan, saya harus menyebutkan bahwa saya melakukan beberapa tes pada laptop saya ( Win 10 x64 ), sama sekali tidak terkait dengan masalah ini, dan ketika tingkat rekursi mencapai nilai di suatu tempat dalam kisaran (990 .. 1000) ( recursionlimit - 1000 (default)), saya dapat StackOverflow :). Jika pohon direktori melebihi batas itu (saya bukan ahli FS , jadi saya tidak tahu apakah itu mungkin), itu bisa menjadi masalah.
Saya juga harus menyebutkan bahwa saya tidak mencoba meningkatkan rekursi karena saya tidak punya pengalaman di area tersebut (berapa banyak yang bisa saya tingkatkan sebelum harus juga menambah tumpukan di OSlevel), tetapi secara teori akan selalu ada kemungkinan kegagalan, jika kedalaman dir lebih besar dari batas rekursi tertinggi yang dimungkinkan (pada mesin itu)
Sampel kode hanya untuk tujuan demonstratif. Itu berarti bahwa saya tidak mempertimbangkan penanganan kesalahan akun (saya tidak berpikir ada coba / kecuali / lain / akhirnya blokir), jadi kodenya tidak kuat (alasannya adalah: membuatnya sesederhana dan sesingkat mungkin ). Untuk produksi , penanganan kesalahan harus ditambahkan juga
Pendekatan lain:
Gunakan Python hanya sebagai pembungkus
Semuanya dilakukan dengan menggunakan teknologi lain
Teknologi itu dipanggil dari Python
Rasa paling terkenal yang saya tahu adalah apa yang saya sebut pendekatan administrator sistem :
Gunakan Python (atau bahasa pemrograman apa pun) untuk menjalankan perintah shell (dan uraikan hasilnya)
Beberapa menganggap ini hack yang rapi
Saya menganggapnya lebih seperti solusi lumpuh ( gainarie ), karena tindakan per se dilakukan dari shell ( cmd dalam kasus ini), dan dengan demikian tidak ada hubungannya dengan Python .
Pemfilteran ( grep/ findstr) atau pemformatan keluaran bisa dilakukan di kedua sisi, tapi saya tidak akan memaksanya. Juga, saya sengaja digunakan os.systemsebagai pengganti subprocess.Popen.
Secara umum pendekatan ini harus dihindari, karena jika beberapa format output perintah sedikit berbeda antara versi OS / rasa, kode parsing harus disesuaikan juga; belum lagi perbedaan antar lokal).
Saya sangat menyukai jawaban Adam , menyarankan agar Anda menggunakan glob(), dari modul dengan nama yang sama. Ini memungkinkan Anda memiliki pola yang cocok dengan *s.
Tetapi seperti yang orang lain tunjukkan dalam komentar, glob()bisa tersandung oleh arah garis miring yang tidak konsisten. Untuk membantu dengan itu, saya sarankan Anda menggunakan join()dan expanduser()fungsi dalam os.pathmodul, dan mungkin juga getcwd()fungsi dalam osmodul.
Sebagai contoh:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
Di atas mengerikan - path telah di-hardcode dan hanya akan bekerja di Windows antara nama drive dan yang \sedang di-hardcod ke path.
from glob import glob
from os.path import join
# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users','admin','*','wlp'))
Di atas berfungsi lebih baik, tetapi bergantung pada nama folder Usersyang sering ditemukan di Windows dan tidak begitu sering ditemukan di OS lain. Itu juga bergantung pada pengguna yang memiliki nama tertentu admin,.
from glob import glob
from os.path import expanduser, join
# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'),'*','wlp'))
Ini berfungsi dengan baik di semua platform.
Contoh hebat lainnya yang bekerja sempurna di seluruh platform dan melakukan sesuatu yang sedikit berbeda:
from glob import glob
from os import getcwd
from os.path import join
# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(),'*','wlp'))
Semoga contoh-contoh ini membantu Anda melihat kekuatan beberapa fungsi yang dapat Anda temukan di modul library Python standar.
def list_files(path):# returns a list of names (with extension, without full path) of all files # in folder path
files =[]for name in os.listdir(path):if os.path.isfile(os.path.join(path, name)):
files.append(name)return files
Untuk hasil yang lebih besar, Anda dapat menggunakan listdir()metode osmodul bersama dengan generator (generator adalah iterator kuat yang mempertahankan kondisinya, ingat?). Kode berikut berfungsi dengan baik dengan kedua versi: Python 2 dan Python 3.
Ini kode:
import os
def files(path):for file in os.listdir(path):if os.path.isfile(os.path.join(path, file)):yield file
for file in files("."):print(file)
The listdir()Metode mengembalikan daftar entri untuk direktori yang diberikan. Metode os.path.isfile()kembali Truejika entri yang diberikan adalah file. Dan yieldoperator berhenti dari func tetapi tetap pada kondisi saat ini, dan hanya mengembalikan nama entri yang terdeteksi sebagai file. Semua hal di atas memungkinkan kita untuk mengulang fungsi generator.
Catatan: os.path.abspath(f)akan menjadi pengganti yang agak lebih murah untuk os.path.join(os.getcwd(),f).
ShadowRanger
Aku akan lebih efisien lagi jika Anda mulai dengan cwd = os.path.abspath('.'), kemudian digunakan cwdsebagai pengganti '.'dan os.getcwd()seluruh beban menghindari panggilan sistem berlebihan.
Hal yang sama dapat dicapai hanya dalam satu baris dengan pathlib:filter(Path.is_file, Path().rglob('*'))
Georgy
9
Seorang guru yang bijak memberi tahu saya bahwa:
Ketika ada beberapa cara mapan untuk melakukan sesuatu, tidak ada satupun yang baik untuk semua kasus.
Saya kemudian akan menambahkan solusi untuk subset masalah: cukup sering, kami hanya ingin memeriksa apakah file cocok dengan string awal dan string akhir, tanpa masuk ke subdirektori. Karena itu kami ingin fungsi yang mengembalikan daftar nama file, seperti:
Jika Anda ingin mendeklarasikan dua fungsi, ini dapat dilakukan:
def file_filter(filename, radical='', extension=''):"Check if a filename matches a radical and extension"ifnot filename:returnFalse
filename = filename.strip()return(filename.startswith(radical)and filename.endswith(extension))def dir_filter(dirname='', radical='', extension=''):"Filter filenames in directory according to radical and extension"ifnot dirname:
dirname ='.'return[filename for filename in os.listdir(dirname)if file_filter(filename, radical, extension)]
Solusi ini dapat dengan mudah digeneralisasikan dengan ekspresi reguler (dan Anda mungkin ingin menambahkan patternargumen, jika Anda tidak ingin pola Anda selalu menempel pada awal atau akhir nama file).
Inilah fungsi tujuan umum saya untuk ini. Ini mengembalikan daftar path file daripada nama file karena saya menemukan itu lebih bermanfaat. Ini memiliki beberapa argumen opsional yang membuatnya serbaguna. Misalnya, saya sering menggunakannya dengan argumen seperti pattern='*.txt'atau subfolders=True.
import os
import fnmatch
def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):"""Return a list of the file paths matching the pattern in the specified
folder, optionally including files inside subfolders.
"""
match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
walked = os.walk(folder)if subfolders else[next(os.walk(folder))]return[os.path.join(root, f)for root, dirnames, filenames in walked
for f in filenames if match(f, pattern)]
Saya akan memberikan sampel satu liner di mana sourcepath dan tipe file dapat diberikan sebagai input. Kode mengembalikan daftar nama file dengan ekstensi csv. Gunakan . seandainya semua file perlu dikembalikan. Ini juga akan memindai subdirektori secara rekursif.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Ubah ekstensi file dan jalur sumber sesuai kebutuhan.
Jika Anda akan menggunakan glob, maka gunakan saja glob('**/*.csv', recursive=True). Tidak perlu menggabungkan ini dengan os.walk()untuk berulang ( recursivedan **didukung sejak Python 3.5).
Jawaban:
os.listdir()
akan memberi Anda semua yang ada di direktori - file dan direktori .Jika Anda hanya ingin file, Anda bisa memfilter ini menggunakan
os.path
:atau Anda bisa menggunakan
os.walk()
yang akan menghasilkan dua daftar untuk setiap direktori yang dikunjungi - membaginya menjadi file dan dir untuk Anda. Jika Anda hanya menginginkan direktori teratas, Anda bisa memecahnya saat pertama kali menghasilkansumber
(_, _, filenames) = walk(mypath).next()
(jika Anda yakin bahwa jalan akan mengembalikan setidaknya satu nilai, yang seharusnya.)f.extend(filenames)
sebenarnya tidak sama denganf = f + filenames
.extend
akan memodifikasif
di tempat, sedangkan menambahkan membuat daftar baru di lokasi memori baru. Ini berartiextend
umumnya lebih efisien daripada+
, tetapi kadang-kadang dapat menyebabkan kebingungan jika beberapa objek menyimpan referensi ke daftar. Terakhir, perlu dicatat bahwaf += filenames
itu setara denganf.extend(filenames)
, bukanf = f + filenames
._, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Saya lebih suka menggunakan
glob
modul, seperti halnya pencocokan pola dan ekspansi.Ini akan mengembalikan daftar dengan file yang diminta:
sumber
/home/user/foo/bar/hello.txt
, maka, jika berjalan di direktorifoo
,glob("bar/*.txt")
akan kembalibar/hello.txt
. Ada beberapa kasus ketika Anda benar-benar menginginkan jalur penuh (yaitu absolut); untuk kasus-kasus tersebut, lihat stackoverflow.com/questions/51520/…glob.glob("*")
akan.x=glob.glob("../train/*.png")
akan memberi saya array jalur saya, selama saya tahu nama foldernya. Keren abis!Cara mendapatkan semua file (dan direktori) di direktori saat ini (Python 3)
Berikut ini, adalah metode sederhana untuk mengambil hanya file di direktori saat ini, menggunakan
os
danlistdir()
fungsinya, dalam Python 3. Eksplorasi lebih lanjut, akan menunjukkan cara mengembalikan folder di direktori, tetapi Anda tidak akan memiliki file di subdirektori, untuk itu Anda bisa menggunakan jalan - bahas nanti).Saya menemukan glob lebih mudah untuk memilih file dengan tipe yang sama atau dengan sesuatu yang sama. Lihatlah contoh berikut:
Fungsi mengembalikan daftar ekstensi yang diberikan (.txt, .docx ecc.) Dalam argumen
Fungsi sekarang mengembalikan daftar file yang cocok dengan string yang Anda berikan sebagai argumen
keluaran
Seperti yang Anda perhatikan, Anda tidak memiliki path lengkap file dalam kode di atas. Jika Anda perlu memiliki path absolut, Anda dapat menggunakan fungsi lain dari
os.path
modul yang disebut_getfullpathname
, menempatkan file yang Anda dapatkanos.listdir()
sebagai argumen. Ada cara lain untuk memiliki path lengkap, seperti yang akan kita periksa nanti (saya ganti, seperti yang disarankan oleh mexmex, dengan _getfullpathnameabspath
).Saya menemukan ini sangat berguna untuk menemukan barang di banyak direktori, dan itu membantu saya menemukan file yang saya tidak ingat namanya:
Dalam Python 2, jika Anda ingin daftar file di direktori saat ini, Anda harus memberikan argumen sebagai '.' atau os.getcwd () dalam metode os.listdir.
Jika saya perlu path absolut dari file:
Dengan
list comprehension
:Atau, gunakan
pathlib.Path()
sebagai gantipathlib.Path(".")
Dalam contoh ini, kami mencari jumlah file yang termasuk dalam semua direktori dan subdirektori.
Sebuah skrip untuk membuat pesanan di komputer Anda menemukan semua file dari jenis (default: pptx) dan menyalinnya di folder baru.
Jika Anda ingin membuat file txt dengan semua nama file:
Dengan fungsi ini Anda dapat membuat file txt yang akan memiliki nama jenis file yang Anda cari (mis. Pngfile.txt) dengan semua path lengkap semua file jenis itu. Kadang-kadang bisa bermanfaat, saya pikir.
sumber
akan mengembalikan daftar semua file dan direktori di "direktori tertentu".
sumber
glob.glob
os.listdir()
selalu mengembalikan nama file belaka (bukan jalur relatif). Apa yangglob.glob()
dikembalikan didorong oleh format jalur dari pola input.Solusi satu baris untuk mendapatkan hanya daftar file (tanpa subdirektori):
atau nama path absolut:
sumber
import os
. Tampak kurang ringkas daripadaglob()
bagi saya.glob()
akan memperlakukannya sebagai file. Metode Anda akan memperlakukannya sebagai direktori.Mendapatkan Path File Lengkap Dari Direktori dan Semua Subdirektorinya
print full_file_paths
yang akan mencetak daftar:['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Jika mau, Anda dapat membuka dan membaca konten, atau hanya fokus pada file dengan ekstensi ".dat" seperti pada kode di bawah ini:
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
sumber
Karena versi 3.4 ada iterator bawaan untuk ini yang jauh lebih efisien daripada
os.listdir()
:pathlib
: Baru dalam versi 3.4.Menurut PEP 428 , tujuan
pathlib
perpustakaan adalah untuk menyediakan hirarki kelas sederhana untuk menangani jalur sistem file dan operasi umum yang dilakukan pengguna atas mereka.os.scandir()
: Baru dalam versi 3.5.Perhatikan bahwa
os.walk()
penggunaanos.scandir()
bukanos.listdir()
dari versi 3.5, dan kecepatannya meningkat 2-20 kali menurut PEP 471 .Izinkan saya juga merekomendasikan membaca komentar ShadowRanger di bawah ini.
sumber
list
. Bisa digunakanp.name
daripada yang pertama sebagaip
alternatif jika lebih disukai.pathlib.Path()
instance karena mereka memiliki banyak metode yang berguna saya tidak ingin membuang-buang limbah. Anda juga dapat memanggilstr(p)
mereka untuk nama jalur.os.scandir
Solusinya akan lebih efisien daripadaos.listdir
denganos.path.is_file
cek atau sejenisnya, bahkan jika Anda memerlukanlist
(sehingga Anda tidak mendapat manfaat dari iterasi malas), karenaos.scandir
menggunakan API yang disediakan OS yang memberi Andais_file
informasi secara gratis karena iterates , tidak ada per-file round trip ke disk untukstat
mereka sama sekali (pada Windows,DirEntry
s membuat Anda lengkapstat
informasi gratis, pada sistem NIX * perlustat
untuk info luaris_file
,is_dir
, dll, tapiDirEntry
cache pada pertamastat
untuk kenyamanan).entry.name
untuk mendapatkan hanya nama file, atauentry.path
untuk mendapatkan path lengkapnya. Tidak ada lagi os.path.join () di semua tempat.Catatan awal
Ketika pertanyaan diajukan, saya membayangkan bahwa Python 2 , adalah versi LTS , namun sampel kode akan dijalankan oleh Python 3 ( .5 ) (saya akan membiarkannya sesuai dengan Python 2 ; mungkin juga, kode apa pun yang dimiliki oleh Python yang akan saya posting, berasal dari v3.5.4 - kecuali ditentukan lain). Itu memiliki konsekuensi yang terkait dengan kata kunci lain dalam pertanyaan: " tambahkan mereka ke dalam daftar ":
Contoh-contoh akan didasarkan pada direktori bernama root_dir dengan struktur berikut (contoh ini untuk Win , tapi saya juga menggunakan pohon yang sama di Lnx ):
Solusi
Pendekatan terprogram:
[Python 3]: os. listdir ( path = '.' )
Contoh yang lebih rumit ( code_os_listdir.py ):
Catatan :
Keluaran :
[Python 3]: os. scandir ( path = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )
Catatan :
os.listdir
[Python 3]: os. walk ( top, topdown = Benar, onerror = Tidak ada, followlinks = Salah )
Catatan :
os.scandir
(os.listdir
pada versi yang lebih lama)[Python 3]: glob. glob ( pathname, *, recursive = False ) ( [Python 3]: glob. iglob ( pathname, *, recursive = False ) )
Catatan :
os.listdir
[Python 3]: class pathlib. Path ( * pathsegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )
Catatan :
[Python 2]: dircache.listdir (path) ( hanya Python 2 )
os.listdir
dengan caching[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) via [Python 3]: ctypes - Pustaka fungsi asing untuk Python ( spesifik POSIX )
code_ctypes.py :
Catatan :
os.walk
format. Saya tidak repot untuk membuatnya rekursif, tetapi mulai dari kode yang ada, itu akan menjadi tugas yang cukup sepeleKeluaran :
[ActiveState.Docs]: win32file.FindFilesW ( Win spesifik)
Catatan :
win32file.FindFilesW
adalah bagian dari [GitHub]: mhammond / pywin32 - Python for Windows (pywin32) Extensions , yang merupakan pembungkus Python di atas WINAPI sCatatan :
Kode dimaksudkan untuk portabel (kecuali tempat yang menargetkan area tertentu - yang ditandai) atau tanda silang:
Berbagai gaya jalur (absolut, kerabat) digunakan di seluruh varian di atas, untuk menggambarkan fakta bahwa "alat" yang digunakan fleksibel dalam arah ini
os.listdir
danos.scandir
gunakan opendir / readdir / closedir ( [MS.Docs]: Fungsi FindFirstFileW / [MS.Docs]: Fungsi FindNextFileW / [MS.Docs]: Fungsi FindClose ) (melalui [GitHub]: python / cpython - (master) cpython / Modul / posixmodule.c )win32file.FindFilesW
menggunakan fungsi-fungsi ( spesifik Menang ) juga (melalui [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / src / win32file.i )_get_dir_content (dari titik # 1. ) dapat diimplementasikan menggunakan salah satu dari pendekatan ini (beberapa akan membutuhkan lebih banyak pekerjaan dan beberapa lagi kurang)
filter_func=lambda x: True
(ini tidak menghapus apapun) dan di dalam _get_dir_content sesuatu seperti:if not filter_func(entry_with_path): continue
(jika fungsi gagal untuk satu entri, itu akan dilewati), tetapi semakin kompleks kodenya, semakin lama waktu yang diperlukan untuk mengeksekusiNota bene! Karena rekursi digunakan, saya harus menyebutkan bahwa saya melakukan beberapa tes pada laptop saya ( Win 10 x64 ), sama sekali tidak terkait dengan masalah ini, dan ketika tingkat rekursi mencapai nilai di suatu tempat dalam kisaran (990 .. 1000) ( recursionlimit - 1000 (default)), saya dapat StackOverflow :). Jika pohon direktori melebihi batas itu (saya bukan ahli FS , jadi saya tidak tahu apakah itu mungkin), itu bisa menjadi masalah.
Saya juga harus menyebutkan bahwa saya tidak mencoba meningkatkan rekursi karena saya tidak punya pengalaman di area tersebut (berapa banyak yang bisa saya tingkatkan sebelum harus juga menambah tumpukan di OSlevel), tetapi secara teori akan selalu ada kemungkinan kegagalan, jika kedalaman dir lebih besar dari batas rekursi tertinggi yang dimungkinkan (pada mesin itu)
Sampel kode hanya untuk tujuan demonstratif. Itu berarti bahwa saya tidak mempertimbangkan penanganan kesalahan akun (saya tidak berpikir ada coba / kecuali / lain / akhirnya blokir), jadi kodenya tidak kuat (alasannya adalah: membuatnya sesederhana dan sesingkat mungkin ). Untuk produksi , penanganan kesalahan harus ditambahkan juga
Pendekatan lain:
Gunakan Python hanya sebagai pembungkus
Rasa paling terkenal yang saya tahu adalah apa yang saya sebut pendekatan administrator sistem :
grep
/findstr
) atau pemformatan keluaran bisa dilakukan di kedua sisi, tapi saya tidak akan memaksanya. Juga, saya sengaja digunakanos.system
sebagai penggantisubprocess.Popen
.Secara umum pendekatan ini harus dihindari, karena jika beberapa format output perintah sedikit berbeda antara versi OS / rasa, kode parsing harus disesuaikan juga; belum lagi perbedaan antar lokal).
sumber
Saya sangat menyukai jawaban Adam , menyarankan agar Anda menggunakan
glob()
, dari modul dengan nama yang sama. Ini memungkinkan Anda memiliki pola yang cocok dengan*
s.Tetapi seperti yang orang lain tunjukkan dalam komentar,
glob()
bisa tersandung oleh arah garis miring yang tidak konsisten. Untuk membantu dengan itu, saya sarankan Anda menggunakanjoin()
danexpanduser()
fungsi dalamos.path
modul, dan mungkin jugagetcwd()
fungsi dalamos
modul.Sebagai contoh:
Di atas mengerikan - path telah di-hardcode dan hanya akan bekerja di Windows antara nama drive dan yang
\
sedang di-hardcod ke path.Di atas berfungsi lebih baik, tetapi bergantung pada nama folder
Users
yang sering ditemukan di Windows dan tidak begitu sering ditemukan di OS lain. Itu juga bergantung pada pengguna yang memiliki nama tertentuadmin
,.Ini berfungsi dengan baik di semua platform.
Contoh hebat lainnya yang bekerja sempurna di seluruh platform dan melakukan sesuatu yang sedikit berbeda:
Semoga contoh-contoh ini membantu Anda melihat kekuatan beberapa fungsi yang dapat Anda temukan di modul library Python standar.
sumber
**
berfungsi selama Anda mengaturrecursive = True
. Lihat dokumen di sini: docs.python.org/3.5/library/glob.html#glob.globsumber
Jika Anda mencari implementasi Python find , ini adalah resep yang saya gunakan agak sering:
Jadi saya membuat paket PyPI darinya dan ada juga repositori GitHub . Saya harap seseorang menemukannya berpotensi berguna untuk kode ini.
sumber
Untuk hasil yang lebih besar, Anda dapat menggunakan
listdir()
metodeos
modul bersama dengan generator (generator adalah iterator kuat yang mempertahankan kondisinya, ingat?). Kode berikut berfungsi dengan baik dengan kedua versi: Python 2 dan Python 3.Ini kode:
The
listdir()
Metode mengembalikan daftar entri untuk direktori yang diberikan. Metodeos.path.isfile()
kembaliTrue
jika entri yang diberikan adalah file. Danyield
operator berhenti dari func tetapi tetap pada kondisi saat ini, dan hanya mengembalikan nama entri yang terdeteksi sebagai file. Semua hal di atas memungkinkan kita untuk mengulang fungsi generator.sumber
Mengembalikan daftar filepath absolut, tidak berulang ke subdirektori
sumber
os.path.abspath(f)
akan menjadi pengganti yang agak lebih murah untukos.path.join(os.getcwd(),f)
.cwd = os.path.abspath('.')
, kemudian digunakancwd
sebagai pengganti'.'
danos.getcwd()
seluruh beban menghindari panggilan sistem berlebihan.Di sini saya menggunakan struktur rekursif.
sumber
pathlib
:filter(Path.is_file, Path().rglob('*'))
Seorang guru yang bijak memberi tahu saya bahwa:
Saya kemudian akan menambahkan solusi untuk subset masalah: cukup sering, kami hanya ingin memeriksa apakah file cocok dengan string awal dan string akhir, tanpa masuk ke subdirektori. Karena itu kami ingin fungsi yang mengembalikan daftar nama file, seperti:
Jika Anda ingin mendeklarasikan dua fungsi, ini dapat dilakukan:
Solusi ini dapat dengan mudah digeneralisasikan dengan ekspresi reguler (dan Anda mungkin ingin menambahkan
pattern
argumen, jika Anda tidak ingin pola Anda selalu menempel pada awal atau akhir nama file).sumber
Menggunakan generator
sumber
Varian lain yang sangat mudah dibaca untuk Python 3.4+ adalah menggunakan pathlib.Path.glob:
Sangat mudah untuk membuat lebih spesifik, misalnya hanya mencari file sumber Python yang bukan tautan simbolik, juga di semua subdirektori:
sumber
Inilah fungsi tujuan umum saya untuk ini. Ini mengembalikan daftar path file daripada nama file karena saya menemukan itu lebih bermanfaat. Ini memiliki beberapa argumen opsional yang membuatnya serbaguna. Misalnya, saya sering menggunakannya dengan argumen seperti
pattern='*.txt'
atausubfolders=True
.sumber
Saya akan memberikan sampel satu liner di mana sourcepath dan tipe file dapat diberikan sebagai input. Kode mengembalikan daftar nama file dengan ekstensi csv. Gunakan . seandainya semua file perlu dikembalikan. Ini juga akan memindai subdirektori secara rekursif.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Ubah ekstensi file dan jalur sumber sesuai kebutuhan.
sumber
glob
, maka gunakan sajaglob('**/*.csv', recursive=True)
. Tidak perlu menggabungkan ini denganos.walk()
untuk berulang (recursive
dan**
didukung sejak Python 3.5).Untuk python2: pip instal rglob
sumber
dircache adalah "Tidak digunakan sejak versi 2.6: Modul dircache telah dihapus di Python 3.0."
sumber