Risposte:
Puoi usare glob
:
import glob, os
os.chdir("/mydir")
for file in glob.glob("*.txt"):
print(file)
o semplicemente os.listdir
:
import os
for file in os.listdir("/mydir"):
if file.endswith(".txt"):
print(os.path.join("/mydir", file))
o se vuoi attraversare la directory, usa os.walk
:
import os
for root, dirs, files in os.walk("/mydir"):
for file in files:
if file.endswith(".txt"):
print(os.path.join(root, file))
for file in f
che per, for files in f
poiché ciò che è nella variabile è un singolo nome file. Ancora meglio sarebbe cambiare il f
to files
e quindi il for for loop potrebbe diventare for file in files
.
file
non è una parola riservata, è solo il nome di una funzione predefinita, quindi è del tutto possibile usarlo come nome di variabile nel proprio codice. Anche se è vero che generalmente si dovrebbero evitare collisioni del genere, file
è un caso speciale perché non c'è quasi mai bisogno di usarlo, quindi è spesso considerato un'eccezione alle linee guida. Se non vuoi farlo, PEP8 consiglia di aggiungere un singolo trattino basso a tali nomi, vale a dire file_
, che dovresti concordare è ancora abbastanza leggibile.
Usa glob .
>>> import glob
>>> glob.glob('./*.txt')
['./outline.txt', './pip-log.txt', './test.txt', './testingvim.txt']
glob
non riuscire a trovare i file in modo ricorsivo se il tuo python è inferiore a 3.5. maggiori informazioni
Qualcosa del genere dovrebbe fare il lavoro
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.txt'):
print file
root, dirs, files
anziché r, d, f
. Molto più leggibile.
Qualcosa del genere funzionerà:
>>> import os
>>> path = '/usr/share/cups/charmaps'
>>> text_files = [f for f in os.listdir(path) if f.endswith('.txt')]
>>> text_files
['euc-cn.txt', 'euc-jp.txt', 'euc-kr.txt', 'euc-tw.txt', ... 'windows-950.txt']
os.path.join
su ogni elemento di text_files
. Potrebbe essere qualcosa del genere text_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.txt')]
.
Puoi semplicemente usare pathlib
s 1 :glob
import pathlib
list(pathlib.Path('your_directory').glob('*.txt'))
o in un ciclo:
for txt_file in pathlib.Path('your_directory').glob('*.txt'):
# do something with "txt_file"
Se lo vuoi ricorsivo puoi usarlo .glob('**/*.txt)
1 Il pathlib
modulo è stato incluso nella libreria standard in Python 3.4. Ma puoi installare back-port di quel modulo anche su versioni precedenti di Python (cioè usando conda
o pip
): pathlib
e pathlib2
.
**/*.txt
non è supportato dalle versioni precedenti di Python, quindi ho risolto questo problema con: foundfiles= subprocess.check_output("ls **/*.txt", shell=True)
for foundfile in foundfiles.splitlines():
print foundfile
pathlib
potesse fare e ho già incluso i requisiti della versione di Python. :) Ma se il tuo approccio non è già stato pubblicato, perché non aggiungerlo come un'altra risposta?
rglob
se si desidera cercare elementi in modo ricorsivo. Ad esempio.rglob('*.txt')
import os
path = 'mypath/path'
files = os.listdir(path)
files_txt = [i for i in files if i.endswith('.txt')]
Mi piace os.walk () :
import os
for root, dirs, files in os.walk(dir):
for f in files:
if os.path.splitext(f)[1] == '.txt':
fullpath = os.path.join(root, f)
print(fullpath)
O con generatori:
import os
fileiter = (os.path.join(root, f)
for root, _, files in os.walk(dir)
for f in files)
txtfileiter = (f for f in fileiter if os.path.splitext(f)[1] == '.txt')
for txt in txtfileiter:
print(txt)
Ecco altre versioni della stessa che producono risultati leggermente diversi:
import glob
for f in glob.iglob("/mydir/*/*.txt"): # generator, search immediate subdirectories
print f
print glob.glob1("/mydir", "*.tx?") # literal_directory, basename_pattern
import fnmatch, os
print fnmatch.filter(os.listdir("/mydir"), "*.tx?") # include dot-files
glob1()
è una funzione di supporto nel glob
modulo che non è elencata nella documentazione di Python. Ci sono alcuni commenti incorporati che descrivono cosa fa nel file sorgente, vedi .../Lib/glob.py
.
glob.glob1()
non è pubblico ma è disponibile su Python 2.4-2.7; 3.0-3.2; PyPy; jython github.com/zed/test_glob1
glob
modulo.
path.py è un'altra alternativa: https://github.com/jaraco/path.py
from path import path
p = path('/path/to/the/directory')
for f in p.files(pattern='*.txt'):
print f
for f in p.walk(pattern='*.txt')
ogni sottocartella
list(p.glob('**/*.py'))
Metodo rapido utilizzando os.scandir in una funzione ricorsiva. Cerca tutti i file con un'estensione specificata nella cartella e nelle sottocartelle.
import os
def findFilesInFolder(path, pathList, extension, subFolders = True):
""" Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)
path: Base directory to find files
pathList: A list that stores all paths
extension: File extension to find
subFolders: Bool. If True, find files in all subfolders under path. If False, only searches files in the specified folder
"""
try: # Trapping a OSError: File permissions problem I believe
for entry in os.scandir(path):
if entry.is_file() and entry.path.endswith(extension):
pathList.append(entry.path)
elif entry.is_dir() and subFolders: # if its a directory, then repeat process as a nested function
pathList = findFilesInFolder(entry.path, pathList, extension, subFolders)
except OSError:
print('Cannot access ' + path +'. Probably a permissions error')
return pathList
dir_name = r'J:\myDirectory'
extension = ".txt"
pathList = []
pathList = findFilesInFolder(dir_name, pathList, extension, True)
Se si cercano directory che contengono 10.000 file, l'aggiunta a un elenco diventa inefficiente. "Produrre" i risultati è una soluzione migliore. Ho anche incluso una funzione per convertire l'output in un Dataframe Pandas.
import os
import re
import pandas as pd
import numpy as np
def findFilesInFolderYield(path, extension, containsTxt='', subFolders = True, excludeText = ''):
""" Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)
path: Base directory to find files
extension: File extension to find. e.g. 'txt'. Regular expression. Or 'ls\d' to match ls1, ls2, ls3 etc
containsTxt: List of Strings, only finds file if it contains this text. Ignore if '' (or blank)
subFolders: Bool. If True, find files in all subfolders under path. If False, only searches files in the specified folder
excludeText: Text string. Ignore if ''. Will exclude if text string is in path.
"""
if type(containsTxt) == str: # if a string and not in a list
containsTxt = [containsTxt]
myregexobj = re.compile('\.' + extension + '$') # Makes sure the file extension is at the end and is preceded by a .
try: # Trapping a OSError or FileNotFoundError: File permissions problem I believe
for entry in os.scandir(path):
if entry.is_file() and myregexobj.search(entry.path): #
bools = [True for txt in containsTxt if txt in entry.path and (excludeText == '' or excludeText not in entry.path)]
if len(bools)== len(containsTxt):
yield entry.stat().st_size, entry.stat().st_atime_ns, entry.stat().st_mtime_ns, entry.stat().st_ctime_ns, entry.path
elif entry.is_dir() and subFolders: # if its a directory, then repeat process as a nested function
yield from findFilesInFolderYield(entry.path, extension, containsTxt, subFolders)
except OSError as ose:
print('Cannot access ' + path +'. Probably a permissions error ', ose)
except FileNotFoundError as fnf:
print(path +' not found ', fnf)
def findFilesInFolderYieldandGetDf(path, extension, containsTxt, subFolders = True, excludeText = ''):
""" Converts returned data from findFilesInFolderYield and creates and Pandas Dataframe.
Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)
path: Base directory to find files
extension: File extension to find. e.g. 'txt'. Regular expression. Or 'ls\d' to match ls1, ls2, ls3 etc
containsTxt: List of Strings, only finds file if it contains this text. Ignore if '' (or blank)
subFolders: Bool. If True, find files in all subfolders under path. If False, only searches files in the specified folder
excludeText: Text string. Ignore if ''. Will exclude if text string is in path.
"""
fileSizes, accessTimes, modificationTimes, creationTimes , paths = zip(*findFilesInFolderYield(path, extension, containsTxt, subFolders))
df = pd.DataFrame({
'FLS_File_Size':fileSizes,
'FLS_File_Access_Date':accessTimes,
'FLS_File_Modification_Date':np.array(modificationTimes).astype('timedelta64[ns]'),
'FLS_File_Creation_Date':creationTimes,
'FLS_File_PathName':paths,
})
df['FLS_File_Modification_Date'] = pd.to_datetime(df['FLS_File_Modification_Date'],infer_datetime_format=True)
df['FLS_File_Creation_Date'] = pd.to_datetime(df['FLS_File_Creation_Date'],infer_datetime_format=True)
df['FLS_File_Access_Date'] = pd.to_datetime(df['FLS_File_Access_Date'],infer_datetime_format=True)
return df
ext = 'txt' # regular expression
containsTxt=[]
path = 'C:\myFolder'
df = findFilesInFolderYieldandGetDf(path, ext, containsTxt, subFolders = True)
Python ha tutti gli strumenti per farlo:
import os
the_dir = 'the_dir_that_want_to_search_in'
all_txt_files = filter(lambda x: x.endswith('.txt'), os.listdir(the_dir))
all_txt_files = list(filter(lambda x: x.endswith('.txt'), os.listdir(the_dir)))
Per ottenere tutti i nomi di file '.txt' all'interno della cartella 'dataPath' come un elenco in modo Pythonic:
from os import listdir
from os.path import isfile, join
path = "/dataPath/"
onlyTxtFiles = [f for f in listdir(path) if isfile(join(path, f)) and f.endswith(".txt")]
print onlyTxtFiles
Prova questo, troverai tutti i tuoi file in modo ricorsivo:
import glob, os
os.chdir("H:\\wallpaper")# use whatever directory you want
#double\\ no single \
for file in glob.glob("**/*.txt", recursive = True):
print(file)
**
. Disponibile solo in Python 3. Quello che non mi piace è la chdir
parte. Non ce n'è bisogno.
filepath = os.path.join('wallpaper')
e poi usarlo come glob.glob(filepath+"**/*.psd", recursive = True)
, che produrrebbe lo stesso risultato.
Ho fatto un test (Python 3.6.4, W7x64) per vedere quale soluzione è la più veloce per una cartella, senza sottodirectory, per ottenere un elenco di percorsi di file completi per i file con un'estensione specifica.
Per farla breve, per questo compito os.listdir()
è il più veloce ed è 1,7 volte più veloce del successivo migliore: os.walk()
(con una pausa!), 2,7 volte più veloce pathlib
, os.scandir()
3,2 volte più veloce di e 3,3 volte più veloce di glob
.
Tieni presente che tali risultati cambieranno quando avrai bisogno di risultati ricorsivi. Se si copia / incolla un metodo di seguito, aggiungere un .lower (), altrimenti .EXT non verrà trovato durante la ricerca di .ext.
import os
import pathlib
import timeit
import glob
def a():
path = pathlib.Path().cwd()
list_sqlite_files = [str(f) for f in path.glob("*.sqlite")]
def b():
path = os.getcwd()
list_sqlite_files = [f.path for f in os.scandir(path) if os.path.splitext(f)[1] == ".sqlite"]
def c():
path = os.getcwd()
list_sqlite_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith(".sqlite")]
def d():
path = os.getcwd()
os.chdir(path)
list_sqlite_files = [os.path.join(path, f) for f in glob.glob("*.sqlite")]
def e():
path = os.getcwd()
list_sqlite_files = [os.path.join(path, f) for f in glob.glob1(str(path), "*.sqlite")]
def f():
path = os.getcwd()
list_sqlite_files = []
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".sqlite"):
list_sqlite_files.append( os.path.join(root, file) )
break
print(timeit.timeit(a, number=1000))
print(timeit.timeit(b, number=1000))
print(timeit.timeit(c, number=1000))
print(timeit.timeit(d, number=1000))
print(timeit.timeit(e, number=1000))
print(timeit.timeit(f, number=1000))
risultati:
# Python 3.6.4
0.431
0.515
0.161
0.548
0.537
0.274
Questo codice mi semplifica la vita.
import os
fnames = ([file for root, dirs, files in os.walk(dir)
for file in files
if file.endswith('.txt') #or file.endswith('.png') or file.endswith('.pdf')
])
for fname in fnames: print(fname)
Usa fnmatch: https://docs.python.org/2/library/fnmatch.html
import fnmatch
import os
for file in os.listdir('.'):
if fnmatch.fnmatch(file, '*.txt'):
print file
Per ottenere una matrice di nomi di file ".txt" da una cartella denominata "dati" nella stessa directory di solito utilizzo questa semplice riga di codice:
import os
fileNames = [fileName for fileName in os.listdir("data") if fileName.endswith(".txt")]
Ti suggerisco di usare fnmatch e il metodo superiore. In questo modo puoi trovare uno dei seguenti:
.
import fnmatch
import os
for file in os.listdir("/Users/Johnny/Desktop/MyTXTfolder"):
if fnmatch.fnmatch(file.upper(), '*.TXT'):
print(file)
Soluzione funzionale con sottodirectory:
from fnmatch import filter
from functools import partial
from itertools import chain
from os import path, walk
print(*chain(*(map(partial(path.join, root), filter(filenames, "*.txt")) for root, _, filenames in walk("mydir"))))
Nel caso in cui la cartella contenga molti file o la memoria sia un vincolo, considerare l'utilizzo di generatori:
def yield_files_with_extensions(folder_path, file_extension):
for _, _, files in os.walk(folder_path):
for file in files:
if file.endswith(file_extension):
yield file
Opzione A: Iterate
for f in yield_files_with_extensions('.', '.txt'):
print(f)
Opzione B: ottieni tutto
files = [f for f in yield_files_with_extensions('.', '.txt')]
Una soluzione copia-pastable simile a quella di ghostdog:
def get_all_filepaths(root_path, ext):
"""
Search all files which have a given extension within root_path.
This ignores the case of the extension and searches subdirectories, too.
Parameters
----------
root_path : str
ext : str
Returns
-------
list of str
Examples
--------
>>> get_all_filepaths('/run', '.lock')
['/run/unattended-upgrades.lock',
'/run/mlocate.daily.lock',
'/run/xtables.lock',
'/run/mysqld/mysqld.sock.lock',
'/run/postgresql/.s.PGSQL.5432.lock',
'/run/network/.ifstate.lock',
'/run/lock/asound.state.lock']
"""
import os
all_files = []
for root, dirs, files in os.walk(root_path):
for filename in files:
if filename.lower().endswith(ext):
all_files.append(os.path.join(root, filename))
return all_files
utilizzare il modulo del sistema operativo Python per trovare file con estensione specifica.
il semplice esempio è qui:
import os
# This is the path where you want to search
path = r'd:'
# this is extension you want to detect
extension = '.txt' # this can be : .jpg .png .xls .log .....
for root, dirs_list, files_list in os.walk(path):
for file_name in files_list:
if os.path.splitext(file_name)[-1] == extension:
file_name_path = os.path.join(root, file_name)
print file_name
print file_name_path # This is the full path of the filter file
Molti utenti hanno risposto con le os.walk
risposte, che includono tutti i file ma anche tutte le directory e le sottodirectory e i loro file.
import os
def files_in_dir(path, extension=''):
"""
Generator: yields all of the files in <path> ending with
<extension>
\param path Absolute or relative path to inspect,
\param extension [optional] Only yield files matching this,
\yield [filenames]
"""
for _, dirs, files in os.walk(path):
dirs[:] = [] # do not recurse directories.
yield from [f for f in files if f.endswith(extension)]
# Example: print all the .py files in './python'
for filename in files_in_dir('./python', '*.py'):
print("-", filename)
O per uno in cui non hai bisogno di un generatore:
path, ext = "./python", ext = ".py"
for _, _, dirfiles in os.walk(path):
matches = (f for f in dirfiles if f.endswith(ext))
break
for filename in matches:
print("-", filename)
Se utilizzerai le corrispondenze per qualcos'altro, potresti voler renderlo un elenco anziché un'espressione del generatore:
matches = [f for f in dirfiles if f.endswith(ext)]
Un metodo semplice usando for
loop:
import os
dir = ["e","x","e"]
p = os.listdir('E:') #path
for n in range(len(p)):
name = p[n]
myfile = [name[-3],name[-2],name[-1]] #for .txt
if myfile == dir :
print(name)
else:
print("nops")
Anche se questo può essere reso più generalizzato.