Come posso elencare tutti i file di una directory in Python e aggiungerli a un list
?
Come posso elencare tutti i file di una directory in Python e aggiungerli a un list
?
Risposte:
os.listdir()
ti porterà tutto ciò che è in una directory: file e directory .
Se vuoi solo i file, puoi filtrarlo usando os.path
:
from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
o potresti usare quello os.walk()
che produrrà due elenchi per ogni directory che visita - suddividendo in file e directory per te. Se vuoi solo la directory principale puoi semplicemente rompere la prima volta che produce
from os import walk
f = []
for (dirpath, dirnames, filenames) in walk(mypath):
f.extend(filenames)
break
(_, _, filenames) = walk(mypath).next()
(se sei sicuro che la camminata restituirà almeno un valore, che dovrebbe.)
f.extend(filenames)
non è effettivamente equivalente a f = f + filenames
. extend
verrà modificato f
sul posto, mentre l'aggiunta crea un nuovo elenco in una nuova posizione di memoria. Questo significa che extend
è generalmente più efficiente di +
, ma a volte può creare confusione se più oggetti contengono riferimenti all'elenco. Infine, vale la pena notare che f += filenames
equivale a f.extend(filenames)
, non è f = f + filenames
.
_, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Preferisco usare il glob
modulo, in quanto fa adattamento ed espansione del modello.
import glob
print(glob.glob("/home/adam/*.txt"))
Restituirà un elenco con i file interrogati:
['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]
/home/user/foo/bar/hello.txt
, quindi, se in esecuzione nella directory foo
, glob("bar/*.txt")
verrà restituito bar/hello.txt
. Ci sono casi in cui in realtà vuoi il percorso completo (cioè assoluto); per questi casi, consultare stackoverflow.com/questions/51520/…
glob.glob("*")
voluto.
x=glob.glob("../train/*.png")
mi darà una serie di percorsi, purché conosca il nome della cartella. Così bello!
Ottieni un elenco di file con Python 2 e 3
os.listdir()
Come ottenere tutti i file (e le directory) nella directory corrente (Python 3)
Di seguito, sono semplici metodi per recuperare solo i file nella directory corrente, usando os
e la listdir()
funzione, in Python 3. Ulteriori esplorazioni, dimostreranno come restituire le cartelle nella directory, ma non si avrà il file nella sottodirectory, per quello che può usare walk - discusso più avanti).
import os
arr = os.listdir()
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
glob
Ho trovato glob più facile selezionare il file dello stesso tipo o con qualcosa in comune. Guarda il seguente esempio:
import glob
txtfiles = []
for file in glob.glob("*.txt"):
txtfiles.append(file)
glob
con comprensione dell'elenco
import glob
mylist = [f for f in glob.glob("*.txt")]
glob
con una funzione
La funzione restituisce un elenco dell'estensione fornita (.txt, .docx ecc.) Nell'argomento
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
l'estensione del codice precedente
La funzione ora restituisce un elenco di file che corrisponde alla stringa che si passa come argomento
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)}")
produzione
example found => []
.py found => ['search.py']
Ottenere il nome completo del percorso con
os.path.abspath
Come hai notato, non hai il percorso completo del file nel codice sopra. Se devi avere il percorso assoluto, puoi usare un'altra funzione del os.path
modulo chiamata _getfullpathname
, mettendo il file che ottieni os.listdir()
come argomento. Esistono altri modi per avere il percorso completo, come controlleremo più avanti (ho sostituito, come suggerito da mexmex, _getfullpathname con 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']
Ottieni il nome percorso completo di un tipo di file in tutte le sottodirectory con
walk
Lo trovo molto utile per trovare cose in molte directory e mi ha aiutato a trovare un file sul quale non ricordavo il nome:
import os
# Getting the current work directory (cwd)
thisdir = os.getcwd()
# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
for file in f:
if file.endswith(".docx"):
print(os.path.join(r, file))
os.listdir()
: recupera i file nella directory corrente (Python 2)
In Python 2, se si desidera l'elenco dei file nella directory corrente, è necessario fornire l'argomento come '.' o os.getcwd () nel metodo os.listdir.
import os
arr = os.listdir('.')
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
Per salire nella struttura delle directory
# Method 1
x = os.listdir('..')
# Method 2
x= os.listdir('/')
Ottieni file:
os.listdir()
in una directory particolare (Python 2 e 3)
import os
arr = os.listdir('F:\\python')
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
Ottieni file di una sottodirectory particolare con
os.listdir()
import os
x = os.listdir("./content")
os.walk('.')
- directory corrente
import os
arr = next(os.walk('.'))[2]
print(arr)
>>> ['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']
next(os.walk('.'))
eos.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:\\')
- ottenere il percorso completo - comprensione della lista
[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
- ottieni il percorso completo - tutti i file nelle directory secondarie **
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()
- Ottieni solo file txt
arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
print(arr_txt)
>>> ['work.txt', '3ebooks.txt']
Utilizzo
glob
per ottenere il percorso completo dei file
Se dovessi aver bisogno del percorso assoluto dei 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
Utilizzo
os.path.isfile
per evitare directory nell'elenco
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']
Utilizzo
pathlib
da 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
Con list comprehension
:
flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]
In alternativa, utilizzare pathlib.Path()
invece dipathlib.Path(".")
Usa il metodo glob in pathlib.Path ()
import pathlib
py = pathlib.Path().glob("*.py")
for file in py:
print(file)
>>> stack_overflow_list.py
>>> stack_overflow_list_tkinter.py
Ottieni tutti e solo i file con os.walk
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']
Ottieni solo i file con next e cammina in una directory
import os
x = next(os.walk('F://python'))[2]
print(x)
>>> ['calculator.bat','calculator.py']
Ottieni solo le directory con next e cammina in una directory
import os
next(os.walk('F://python'))[1] # for the current dir use ('.')
>>> ['python3','others']
Ottieni tutti i nomi dei subdir con
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()
da Python 3.5 e versioni successive
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
Esempi:
Ex. 1: quanti file ci sono nelle sottodirectory?
In questo esempio, cerchiamo il numero di file inclusi in tutte le directory e nelle sue sottodirectory.
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 += 1
return dir + " : " + str(counter) + "files"
print(count("F:\\python"))
>>> 'F:\\\python' : 12057 files'
Ex.2: Come copiare tutti i file da una directory a un'altra?
Uno script per effettuare l'ordine nel tuo computer che trova tutti i file di un tipo (impostazione predefinita: pptx) e li copia in una nuova cartella.
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 += 1
if 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
>>> ------------------------
>>> ==> Found in: `_compiti18` : 3 files
Ex. 3: Come ottenere tutti i file in un file txt
Nel caso in cui si desideri creare un file txt con tutti i nomi di 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)
Esempio: txt con tutti i file di un disco rigido
"""
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")
Tutto il file di C: \ in un file di testo
Questa è una versione più breve del codice precedente. Cambia la cartella da cui iniziare a trovare i file se devi iniziare da un'altra posizione. Questo codice genera un file di testo di 50 mb sul mio computer con qualcosa in meno di 500.000 righe con file con il percorso completo.
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")
Come scrivere un file con tutti i percorsi in una cartella di un tipo
Con questa funzione puoi creare un file txt che avrà il nome di un tipo di file che cerchi (es. Pngfile.txt) con tutto il percorso completo di tutti i file di quel tipo. A volte può essere utile, penso.
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
(Novità) Trova tutti i file e aprili con la GUI di tkinter
Volevo solo aggiungere in questo 2019 una piccola app per cercare tutti i file in una directory ed essere in grado di aprirli facendo doppio clic sul nome del file nell'elenco.
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()
import os
os.listdir("somedirectory")
restituirà un elenco di tutti i file e le directory in "somedirectory".
glob.glob
os.listdir()
restituisce sempre semplici nomi di file (non percorsi relativi). Ciò che glob.glob()
ritorna è guidato dal formato del percorso del modello di input.
Una soluzione su una riga per ottenere solo un elenco di file (nessuna sottodirectory):
filenames = next(os.walk(path))[2]
o nomi di percorso assoluti:
paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
import os
. Sembra meno conciso che glob()
a me.
glob()
lo tratterebbe come un file. Il tuo metodo lo tratterà come una directory.
Ottenere percorsi di file completi da una directory e da tutte le sue sottodirectory
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")
print full_file_paths
che stamperà l'elenco:
['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Se lo desideri, puoi aprire e leggere i contenuti o concentrarti solo sui file con estensione ".dat" come nel codice seguente:
for f in full_file_paths:
if f.endswith(".dat"):
print f
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
Dalla versione 3.4 ci sono iteratori integrati per questo che sono molto più efficienti di os.listdir()
:
pathlib
: Nuovo nella versione 3.4.
>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]
Secondo PEP 428 , lo scopo della pathlib
libreria è fornire una semplice gerarchia di classi per gestire i percorsi del filesystem e le operazioni comuni che gli utenti eseguono su di essi.
os.scandir()
: Nuovo nella versione 3.5.
>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]
Si noti che os.walk()
utilizza os.scandir()
invece che os.listdir()
dalla versione 3.5 e la sua velocità è stata aumentata di 2-20 volte secondo PEP 471 .
Vorrei anche raccomandare di leggere il commento di ShadowRanger qui sotto.
list
. Potrebbe usare al p.name
posto del primo in p
alternativa, se preferito.
pathlib.Path()
istanze poiché hanno molti metodi utili che non vorrei sprecare. Puoi anche chiamarli str(p)
per i nomi dei percorsi.
os.scandir
soluzione sarà più efficiente che os.listdir
con un os.path.is_file
controllo o simili, anche se hai bisogno di un list
(quindi non trarrai vantaggio dall'iterazione lenta), perché os.scandir
utilizza le API fornite dal sistema operativo che ti forniscono le is_file
informazioni gratuitamente mentre scorre , non per file di andata e ritorno al disco per stat
loro a tutti (su Windows, le DirEntry
s farti completa stat
informazioni per libero, su sistemi * nix ha bisogno di stat
per informazioni al di là is_file
, is_dir
e così via, ma DirEntry
cache sul primo stat
per comodità).
entry.name
per ottenere solo il nome del file o entry.path
per ottenere il suo percorso completo. Non più os.path.join () dappertutto.
Quando è stata posta la domanda, immagino che Python 2 fosse la versione LTS , tuttavia gli esempi di codice verranno eseguiti da Python 3 ( .5 ) (li terrò il più possibile compatibili con Python 2 ; inoltre, qualsiasi codice appartenente a Python che ho intenzione di pubblicare è dalla v3.5.4 - se non diversamente specificato). Ciò ha conseguenze relative a un'altra parola chiave nella domanda: " aggiungili a un elenco ":
>>> 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'>)
Gli esempi saranno basati su una directory chiamata root_dir con la seguente struttura (questo esempio è per Win , ma sto usando lo stesso albero anche su Lnx ):
E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir" Folder PATH listing for volume Work Volume serial number is 00000029 3655:6FED E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR ¦ file0 ¦ file1 ¦ +---dir0 ¦ +---dir00 ¦ ¦ ¦ file000 ¦ ¦ ¦ ¦ ¦ +---dir000 ¦ ¦ file0000 ¦ ¦ ¦ +---dir01 ¦ ¦ file010 ¦ ¦ file011 ¦ ¦ ¦ +---dir02 ¦ +---dir020 ¦ +---dir0200 +---dir1 ¦ file10 ¦ file11 ¦ file12 ¦ +---dir2 ¦ ¦ file20 ¦ ¦ ¦ +---dir20 ¦ file200 ¦ +---dir3
[Python 3]: os. listdir ( path = '.' )
Restituisce un elenco contenente i nomi delle voci nella directory fornite dal percorso. L'elenco è in ordine arbitrario e non include le voci speciali
'.'
e'..'
...
>>> 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']
Un esempio più elaborato ( 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()
Note :
Uscita :
(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']
[Python 3]: os. scandir ( path = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )
Restituisce un iteratore di oggetti os.DirEntry corrispondenti alle voci nella directory fornite dal percorso . Le voci sono rese in ordine arbitrario e le voci speciali
'.'
e'..'
non sono incluse.L'uso di scandir () anziché listdir () può aumentare significativamente le prestazioni del codice che necessita anche di informazioni sul tipo di file o sugli attributi di file, poiché gli oggetti os.DirEntry espongono queste informazioni se il sistema operativo le fornisce durante la scansione di una directory. Tutti i metodi os.DirEntry possono eseguire una chiamata di sistema, ma is_dir () e is_file () di solito richiedono solo una chiamata di sistema per collegamenti simbolici; os.DirEntry.stat () richiede sempre una chiamata di sistema su Unix ma ne richiede solo una per i collegamenti simbolici su 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
Note :
os.listdir
[Python 3]: os. walk ( top, topdown = True, onerror = None, followlink = False )
Generare i nomi dei file in un albero di directory percorrendo l'albero dall'alto verso il basso o dal basso verso l'alto. Per ogni directory nella struttura di radice in directory superiore (compresa la parte superiore stessa), produce un 3-tupla (
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', [], [])
Note :
os.scandir
( os.listdir
nelle versioni precedenti)[Python 3]: glob. glob ( nome percorso, *, ricorsivo = falso ) ( [Python 3]: glob. iglob ( percorso, *, ricorsivo = falso ) )
Restituisce un elenco possibilmente vuoto di nomi di percorso che corrispondono a nome percorso , che deve essere una stringa contenente una specifica del percorso. il percorso può essere assoluto (simile
/usr/src/Python-1.5/Makefile
) o relativo (simile../../Tools/*/*.gif
) e può contenere caratteri jolly in stile shell. I link simbolici non funzionanti sono inclusi nei risultati (come nella shell).
...
Modificato nella versione 3.5 : Supporto per globi ricorsivi utilizzando "**
".
>>> 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
Note :
os.listdir
[Python 3]: pathlib di classe. Path ( * pathegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )
>>> 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("*") if not item.is_dir()] # Display paths (including parent) for files only ['root_dir\\file0', 'root_dir\\file1']
Note :
[Python 2]: dircache.listdir (percorso) ( solo Python 2 )
os.listdir
con memorizzazione nella cachedef listdir(path):
"""List directory contents, using cache."""
try:
cached_mtime, list = cache[path]
del cache[path]
except KeyError:
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
[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) tramite [Python 3]: ctypes - Una libreria di funzioni esterne per Python ( specifica POSIX )
ctypes è una libreria di funzioni estranee per Python. Fornisce tipi di dati compatibili con C e consente di chiamare funzioni in DLL o librerie condivise. Può essere usato per avvolgere queste librerie in Python puro.
code_ctypes.py :
#!/usr/bin/env python3
import sys
from ctypes import Structure, \
c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
CDLL, POINTER, \
create_string_buffer, get_errno, set_errno, cast
DT_DIR = 4
DT_REG = 8
char256 = c_char * 256
class LinuxDirent64(Structure):
_fields_ = [
("d_ino", c_ulonglong),
("d_off", c_longlong),
("d_reclen", c_ushort),
("d_type", c_ubyte),
("d_name", char256),
]
LinuxDirent64Ptr = POINTER(LinuxDirent64)
libc_dll = this_process = CDLL(None, use_errno=True)
# ALWAYS set argtypes and restype for functions, otherwise it's UB!!!
opendir = libc_dll.opendir
readdir = libc_dll.readdir
closedir = libc_dll.closedir
def get_dir_content(path):
ret = [path, list(), list()]
dir_stream = opendir(create_string_buffer(path.encode()))
if (dir_stream == 0):
print("opendir returned NULL (errno: {:d})".format(get_errno()))
return ret
set_errno(0)
dirent_addr = readdir(dir_stream)
while dirent_addr:
dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
dirent = dirent_ptr.contents
name = dirent.d_name.decode()
if dirent.d_type & DT_DIR:
if name not in (".", ".."):
ret[1].append(name)
elif dirent.d_type & DT_REG:
ret[2].append(name)
dirent_addr = readdir(dir_stream)
if get_errno():
print("readdir returned NULL (errno: {:d})".format(get_errno()))
closedir(dir_stream)
return ret
def main():
print("{:s} on {:s}\n".format(sys.version, sys.platform))
root_dir = "root_dir"
entries = get_dir_content(root_dir)
print(entries)
if __name__ == "__main__":
main()
Note :
os.walk
formato di. Non mi sono preoccupato di renderlo ricorsivo, ma a partire dal codice esistente, sarebbe stato un compito abbastanza banaleUscita :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]> ./code_ctypes.py 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux ['root_dir', ['dir2', 'dir1', 'dir3', 'dir0'], ['file1', 'file0']]
[ActiveState.Docs]: win32file.FindFilesW ( specifico per Win )
Recupera un elenco di nomi file corrispondenti, utilizzando l'API Unicode di Windows. Un'interfaccia all'API FindFirstFileW / FindNextFileW / Trova chiudi le funzioni.
>>> 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 long 8 >>> [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] not in (".", "..")] # 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']
Note :
win32file.FindFilesW
è parte di [GitHub]: mhammond / pywin32 - Python per Windows (pywin32) Extensions , che è un Python involucro sopra WINAPI sNote :
Il codice è pensato per essere portatile (tranne i luoghi che hanno come target un'area specifica - che sono contrassegnati) o incrociati:
Stili di percorso multipli (assoluti, relativi) sono stati utilizzati tra le varianti sopra, per illustrare il fatto che gli "strumenti" utilizzati sono flessibili in questa direzione
os.listdir
e os.scandir
usa opendir / readdir / closedir ( [MS.Docs]: funzione FindFirstFileW / [MS.Docs]: funzione FindNextFileW / [MS.Docs]: funzione FindClose ) (tramite [GitHub]: python / cpython - (master) cpython / Moduli / posixmodule.c )
win32file.FindFilesW
usa anche quelle funzioni ( specifiche di Win ) (tramite [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / src / win32file.i )
_get_dir_content (dal punto 1 ) può essere implementato utilizzando uno di questi approcci (alcuni richiederanno più lavoro e altri meno)
filter_func=lambda x: True
(questo non rimuove qualcosa) e dentro _get_dir_content qualcosa del tipo: if not filter_func(entry_with_path): continue
(se la funzione fallisce per una voce, verrà saltata), ma più il codice diventa complesso, più tempo ci vorrà per eseguireNota bene! Da quando viene utilizzata la ricorsione, devo dire che ho fatto alcuni test sul mio laptop ( Win 10 x64 ), totalmente estraneo a questo problema, e quando il livello di ricorsione raggiungeva valori da qualche parte nell'intervallo (990 .. 1000) ( recursionlimit - 1000 (impostazione predefinita)), ho StackOverflow :). Se l'albero delle directory supera quel limite (non sono un esperto di FS , quindi non so se sia possibile), potrebbe essere un problema.
Devo anche menzionare che non ho provato ad aumentare il limite di ricorsione perché non ho esperienza nell'area (quanto posso aumentarlo prima di dover aumentare anche lo stack sul sistema operativolivello), ma in teoria ci sarà sempre la possibilità di fallimento, se la profondità dir è maggiore del limite di ricorsione più alto possibile (su quella macchina)
Gli esempi di codice sono solo a scopo dimostrativo. Ciò significa che non ho preso in considerazione la gestione degli errori (non credo che ci sia alcun tentativo / tranne / else / finally block), quindi il codice non è robusto (il motivo è: mantenerlo il più semplice e breve possibile ). Per la produzione , è necessario aggiungere anche la gestione degli errori
Usa Python solo come wrapper
Il sapore più famoso che conosco è quello che chiamo l' approccio dell'amministratore di sistema :
grep
/ findstr
) o la formattazione dell'output potrebbero essere eseguiti su entrambi i lati, ma non ho intenzione di insistere. Inoltre, ho usato deliberatamente os.system
invece di subprocess.Popen
.(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")" dir0 dir1 dir2 dir3 file0 file1
In generale questo approccio deve essere evitato, poiché se un formato di output del comando differisce leggermente tra versioni / sapori del sistema operativo , anche il codice di analisi dovrebbe essere adattato; per non parlare delle differenze tra i locali).
Mi è davvero piaciuta la risposta di Adamk , suggerendoti di usare glob()
, dal modulo con lo stesso nome. Questo ti permette di avere un pattern matching con *
s.
Ma come altre persone hanno sottolineato nei commenti, glob()
possono inciampare in direzioni incoerenti. Per aiutarti, ti suggerisco di usare le funzioni join()
e expanduser()
nel os.path
modulo, e forse anche la getcwd()
funzione nel os
modulo.
Come esempi:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
Quanto sopra è terribile - il percorso è stato hardcoded e funzionerà sempre e solo su Windows tra il nome dell'unità e il \
codice hardcoded nel percorso.
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'))
Quanto sopra funziona meglio, ma si basa sul nome della cartella Users
che si trova spesso su Windows e non così spesso trovato su altri sistemi operativi. Essa si basa anche su l'utente avere un nome specifico, 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'))
Funziona perfettamente su tutte le piattaforme.
Un altro ottimo esempio che funziona perfettamente su tutte le piattaforme e fa qualcosa di leggermente diverso:
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'))
Spero che questi esempi ti aiutino a vedere la potenza di alcune delle funzioni che puoi trovare nei moduli della libreria Python standard.
**
funziona tutto il tempo impostato recursive = True
. Vedi i documenti qui: docs.python.org/3.5/library/glob.html#glob.glob
Se stai cercando un'implementazione di Python di find , questa è una ricetta che uso piuttosto frequentemente:
from findtools.find_files import (find_files, Match)
# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)
for found_file in found_files:
print found_file
Quindi ne ho ricavato un pacchetto PyPI e c'è anche un repository GitHub . Spero che qualcuno lo trovi potenzialmente utile per questo codice.
Per risultati migliori, puoi usare il listdir()
metodo del os
modulo insieme a un generatore (un generatore è un potente iteratore che mantiene il suo stato, ricordi?). Il codice seguente funziona bene con entrambe le versioni: Python 2 e Python 3.
Ecco un codice:
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)
Il listdir()
metodo restituisce l'elenco delle voci per la directory specificata. Il metodo os.path.isfile()
restituisce True
se la voce specificata è un file. E l' yield
operatore chiude la funzione ma mantiene il suo stato corrente e restituisce solo il nome della voce rilevata come file. Tutto quanto sopra ci consente di passare in rassegna la funzione generatore.
Restituendo un elenco di percorsi file assoluti, non ricorre nelle sottodirectory
L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]
os.path.abspath(f)
sarebbe un sostituto un po 'più economico os.path.join(os.getcwd(),f)
.
cwd = os.path.abspath('.')
, poi usato al cwd
posto di '.'
e in os.getcwd()
tutto per evitare un sacco di chiamate di sistema ridondanti.
import os
import os.path
def get_files(target_dir):
item_list = os.listdir(target_dir)
file_list = list()
for item in item_list:
item_dir = os.path.join(target_dir,item)
if os.path.isdir(item_dir):
file_list += get_files(item_dir)
else:
file_list.append(item_dir)
return file_list
Qui uso una struttura ricorsiva.
Un saggio insegnante mi disse una volta che:
Quando ci sono diversi modi stabiliti per fare qualcosa, nessuno di loro è buono per tutti i casi.
Aggiungerò quindi una soluzione per un sottoinsieme del problema: abbastanza spesso, vogliamo solo verificare se un file corrisponde a una stringa iniziale e una stringa finale, senza andare nelle sottodirectory. Vorremmo quindi una funzione che restituisca un elenco di nomi di file, come:
filenames = dir_filter('foo/baz', radical='radical', extension='.txt')
Se ti interessa dichiarare prima due funzioni, puoi farlo:
def file_filter(filename, radical='', extension=''):
"Check if a filename matches a radical and extension"
if not filename:
return False
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"
if not dirname:
dirname = '.'
return [filename for filename in os.listdir(dirname)
if file_filter(filename, radical, extension)]
Questa soluzione potrebbe essere facilmente generalizzata con espressioni regolari (e potresti voler aggiungere un pattern
argomento, se non vuoi che i tuoi pattern rimangano sempre all'inizio o alla fine del nome del file).
Un'altra variante molto leggibile per Python 3.4+ è l'utilizzo di pathlib.Path.glob:
from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]
È semplice rendere più specifici, ad esempio cercare solo i file sorgente Python che non sono collegamenti simbolici, anche in tutte le sottodirectory:
[f for f in Path(folder).glob('**/*.py') if not f.is_symlink()]
Ecco la mia funzione generale per questo. Restituisce un elenco di percorsi di file piuttosto che nomi di file poiché l'ho trovato più utile. Ha alcuni argomenti opzionali che lo rendono versatile. Ad esempio, lo uso spesso con argomenti come pattern='*.txt'
o 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)]
Fornirò un esempio di copertina in cui sourcepath e il tipo di file possono essere forniti come input. Il codice restituisce un elenco di nomi di file con estensione CSV. Usa . nel caso in cui tutti i file debbano essere restituiti. Ciò analizzerà anche ricorsivamente le sottodirectory.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modificare le estensioni dei file e il percorso di origine secondo necessità.
glob
, usa semplicemente glob('**/*.csv', recursive=True)
. Non è necessario combinare questo con os.walk()
recurse ( recursive
e **
sono supportati da Python 3.5).
Per python2: pip installa rglob
import rglob
file_list=rglob.rglob("/home/base/dir/", "*")
print file_list
dircache è " Obsoleto dalla versione 2.6: Il modulo dircache è stato rimosso in Python 3.0."
import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
if len(list[i]) != check:
temp.append(list[i-1])
check = len(list[i])
else:
i = i + 1
count = count - 1
print temp