os.listdir()vous obtiendra tout ce qui est dans un répertoire - fichiers et répertoires .
Si vous voulez seulement des fichiers, vous pouvez soit filtrer cela en utilisant os.path:
from os import listdir
from os.path import isfile, join
onlyfiles =[f for f in listdir(mypath)if isfile(join(mypath, f))]
ou vous pouvez utiliser os.walk()qui donne deux listes pour chaque répertoire qu'il visite - division en fichiers et répertoires pour vous. Si vous ne voulez que le répertoire supérieur, vous pouvez simplement casser la première fois qu'il donne
from os import walk
f =[]for(dirpath, dirnames, filenames)in walk(mypath):
f.extend(filenames)break
Un peu plus simple: (_, _, filenames) = walk(mypath).next() (si vous êtes sûr que la marche renverra au moins une valeur, ce qu'elle devrait.)
misterbee
9
Légère modification pour stocker les chemins complets: for (dirpath, dirnames, filenames) in os.walk (mypath): checksum_files.extend (os.path.join (dirpath, filename) for filename in filenames) break
okigan
150
f.extend(filenames)n'est pas réellement équivalent à f = f + filenames. extendmodifiera fsur place, tandis que l'ajout crée une nouvelle liste dans un nouvel emplacement de mémoire. Cela signifie extendest généralement plus efficace que +, mais cela peut parfois prêter à confusion si plusieurs objets contiennent des références à la liste. Enfin, il convient de noter que cela f += filenameséquivaut à f.extend(filenames), nonf = f + filenames .
Benjamin Hodgson
30
@misterbee, votre solution est la meilleure, juste une petite amélioration:_, _, filenames = next(walk(mypath), (None, None, []))
bgusach
35
en utilisation python 3.x(_, _, filenames) = next(os.walk(mypath))
ET-CS
1684
Je préfère utiliser le globmodule, car il fait la correspondance et l'expansion des modèles.
import glob
print(glob.glob("/home/adam/*.txt"))
Il renverra une liste avec les fichiers interrogés:
pour clarifier, cela ne renvoie pas le "chemin complet"; il renvoie simplement l'expansion du globe, quelle qu'elle soit. Par exemple, étant donné /home/user/foo/bar/hello.txt, si en cours d'exécution dans le répertoire foo, le glob("bar/*.txt")retourne bar/hello.txt. Il y a des cas où vous voulez en fait le chemin complet (c'est-à-dire absolu); pour ces cas, voir stackoverflow.com/questions/51520/…
ne répond pas à cette question. glob.glob("*")aurait.
Jean-François Fabre
beau!!!! alors .... x=glob.glob("../train/*.png")me donnera un tableau de mes chemins, tant que je connais le nom du dossier. Trop cool!
Jennifer Crosby
860
Obtenez une liste de fichiers avec Python 2 et 3
os.listdir()
Comment obtenir tous les fichiers (et répertoires) dans le répertoire courant (Python 3)
Voici des méthodes simples pour récupérer uniquement les fichiers dans le répertoire en cours, en utilisant os et la listdir()fonction, en Python 3. Une exploration plus approfondie, montrera comment retourner les dossiers dans le répertoire, mais vous n'aurez pas le fichier dans le sous-répertoire, pour cela vous peut utiliser la marche - discuté plus tard).
import os
arr = os.listdir()print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
glob
J'ai trouvé glob plus facile de sélectionner le fichier du même type ou avec quelque chose en commun. Regardez l'exemple suivant:
import glob
txtfiles =[]for file in glob.glob("*.txt"):
txtfiles.append(file)
glob avec compréhension de liste
import glob
mylist =[f for f in glob.glob("*.txt")]
glob avec une fonction
La fonction renvoie une liste de l'extension donnée (.txt, .docx ecc.) Dans l'argument
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 étendre le code précédent
La fonction retourne maintenant une liste de fichiers correspondant à la chaîne que vous passez en argument
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)}")
production
example found =>[].py found =>['search.py']
Obtention du nom de chemin complet avec os.path.abspath
Comme vous l'avez remarqué, vous n'avez pas le chemin complet du fichier dans le code ci-dessus. Si vous devez avoir le chemin absolu, vous pouvez utiliser une autre fonction du os.pathmodule appelé _getfullpathname, en plaçant le fichier dont vous obtenez os.listdir()comme argument. Il existe d'autres façons d'avoir le chemin complet, comme nous le verrons plus tard (j'ai remplacé, comme suggéré par mexmex, _getfullpathname avec 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']
Obtenez le nom de chemin complet d'un type de fichier dans tous les sous-répertoires avec walk
Je trouve cela très utile pour trouver des choses dans de nombreux répertoires, et cela m'a aidé à trouver un fichier dont je ne me souvenais pas du nom:
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(): récupère les fichiers dans le répertoire courant (Python 2)
En Python 2, si vous voulez la liste des fichiers dans le répertoire courant, vous devez donner l'argument comme '.' ou os.getcwd () dans la méthode os.listdir.
import os
arr = os.listdir('.')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Pour remonter dans l'arborescence des répertoires
# Method 1
x = os.listdir('..')# Method 2
x= os.listdir('/')
Récupérer des fichiers: os.listdir()dans un répertoire particulier (Python 2 et 3)
import os
arr = os.listdir('F:\\python')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Récupère les fichiers d'un sous-répertoire particulier avec os.listdir()
import os
x = os.listdir("./content")
os.walk('.') - répertoire actuel
import os
arr = next(os.walk('.'))[2]print(arr)>>>['5bs_Turismo1.pdf','5bs_Turismo1.pptx','esperienza.txt']
next(os.walk('.')) et 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:\\') - obtenir le chemin complet - liste de compréhension
[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 - obtenir le chemin complet - tous les fichiers dans les sous-répertoires **
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() - obtenir uniquement des fichiers txt
arr_txt =[x for x in os.listdir()if x.endswith(".txt")]print(arr_txt)>>>['work.txt','3ebooks.txt']
Utilisation globpour obtenir le chemin complet des fichiers
Si j'ai besoin du chemin absolu des fichiers:
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
Utilisation os.path.isfilepour éviter les répertoires dans la liste
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']
Utilisation pathlibde 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
Avec list comprehension:
flist =[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Vous pouvez également utiliser pathlib.Path()au lieu depathlib.Path(".")
Obtenez tous et seulement les fichiers avec 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']
Récupère uniquement les fichiers avec next et marche dans un répertoire
import os
x = next(os.walk('F://python'))[2]print(x)>>>['calculator.bat','calculator.py']
Obtenez uniquement les répertoires avec next et parcourez un répertoire
import os
next(os.walk('F://python'))[1]# for the current dir use ('.')>>>['python3','others']
Obtenez tous les noms des sous-répertoires avec 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() à partir de Python 3.5 et supérieur
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
Exemples:
Ex. 1: Combien de fichiers y a-t-il dans les sous-répertoires?
Dans cet exemple, nous recherchons le nombre de fichiers inclus dans tout le répertoire et ses sous-répertoires.
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'
Ex.2: Comment copier tous les fichiers d'un répertoire vers un autre?
Un script pour mettre de l'ordre dans votre ordinateur en trouvant tous les fichiers d'un type (par défaut: pptx) et en les copiant dans un nouveau dossier.
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: Comment obtenir tous les fichiers dans un fichier txt
Dans le cas où vous souhaitez créer un fichier txt avec tous les noms de fichiers:
import os
mylist =""with open("filelist.txt","w", encoding="utf-8")as file:for eachfile in os.listdir():
mylist += eachfile +"\n"
file.write(mylist)
Exemple: txt avec tous les fichiers d'un disque dur
"""
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")
Tout le fichier de C: \ dans un fichier texte
Il s'agit d'une version plus courte du code précédent. Modifiez le dossier où commencer à rechercher les fichiers si vous devez commencer à partir d'une autre position. Ce code génère un fichier texte de 50 Mo sur mon ordinateur avec quelque chose de moins de 500 000 lignes avec des fichiers avec le chemin complet.
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")
Comment écrire un fichier avec tous les chemins dans un dossier d'un type
Avec cette fonction, vous pouvez créer un fichier txt qui aura le nom d'un type de fichier que vous recherchez (ex. Pngfile.txt) avec tout le chemin complet de tous les fichiers de ce type. Cela peut être utile parfois, je pense.
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
(Nouveau) Trouvez tous les fichiers et ouvrez-les avec l'interface graphique de tkinter
Je voulais juste ajouter dans cette 2019 une petite application pour rechercher tous les fichiers dans un répertoire et pouvoir les ouvrir en double-cliquant sur le nom du fichier dans la liste.
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()
Ceci est un méli-mélo de trop de réponses aux questions non posées ici. Il peut également être utile d'expliquer quelles sont les mises en garde ou les approches recommandées. Je ne suis pas mieux de savoir une façon contre 20 façons de faire la même chose, sauf si je sais aussi laquelle est la plus appropriée à utiliser quand.
cs95
Ok, dès que possible, je vais jeter un coup d'œil à ma réponse et essayer de la rendre plus propre et avec des informations plus utiles sur la différence entre les méthodes, etc.
Giovanni G. PY
Vous ne devez pas déterminer l'extension du fichier en vérifiant si le nom de fichier contient une sous-chaîne. Cela pourrait causer de nombreux problèmes. Je recommande de toujours vérifier si le nom de fichier se termine par la sous-chaîne particulière.
ni1ight
Ok, @ n1light j'ai changé le code ...
Giovanni G. PY
812
import os
os.listdir("somedirectory")
renverra une liste de tous les fichiers et répertoires dans "somedirectory".
Cela renvoie le chemin relatif des fichiers, par rapport au chemin complet renvoyé parglob.glob
xji
22
@JIXiang: os.listdir()renvoie toujours de simples noms de fichiers (pas des chemins relatifs). Ce qui glob.glob()retourne est déterminé par le format de chemin du modèle d'entrée.
mklement0
os.listdir () -> Il répertorie toujours le répertoire et le fichier à l'intérieur de l'emplacement fourni. Existe-t-il un moyen de répertorier uniquement le répertoire et non les fichiers?
RonyA
160
Une solution en ligne pour obtenir uniquement la liste des fichiers (pas de sous-répertoires):
filenames = next(os.walk(path))[2]
ou chemins absolus:
paths =[os.path.join(path, fn)for fn in next(os.walk(path))[2]]
Un seul revêtement si vous l'avez déjà fait import os. Semble moins concis qu'à glob()moi.
ArtOfWarfare
4
le problème avec glob est qu'un dossier appelé 'something.something' serait retourné par glob ('/ home / adam /*.*')
Remi
6
Sur OS X, il y a quelque chose appelé un bundle. C'est un répertoire qui devrait généralement être traité comme un fichier (comme un .tar). Souhaitez-vous que ceux-ci soient traités comme un fichier ou un répertoire? Utiliser glob()le traiterait comme un fichier. Votre méthode le traiterait comme un répertoire.
ArtOfWarfare
132
Obtention de chemins de fichiers complets à partir d'un répertoire et de tous ses sous-répertoires
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")
Le chemin que j'ai fourni dans la fonction ci-dessus contenait 3 fichiers - deux d'entre eux dans le répertoire racine et un autre dans un sous-dossier appelé "SUBFOLDER". Vous pouvez maintenant faire des choses comme:
Si vous le souhaitez, vous pouvez ouvrir et lire le contenu, ou vous concentrer uniquement sur les fichiers avec l'extension ".dat" comme dans le code ci-dessous:
for f in full_file_paths:if f.endswith(".dat"):print f
>>>import pathlib
>>>[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Selon PEP 428 , l'objectif de la pathlibbibliothèque est de fournir une hiérarchie simple de classes pour gérer les chemins de système de fichiers et les opérations courantes que les utilisateurs effectuent sur eux.
Merci! Je pense que c'est la seule solution qui ne revient pas directement a list. Pourrait utiliser à la p.nameplace du premier palternativement si vous préférez.
jeromej
1
Bienvenue! Je préférerais générer des pathlib.Path()instances car elles ont de nombreuses méthodes utiles que je ne voudrais pas gaspiller. Vous pouvez également faire appel str(p)à eux pour les noms de chemin.
SzieberthAdam
6
Remarque: La os.scandirsolution sera plus efficace os.listdirqu'avec une os.path.is_filevérification ou similaire, même si vous en avez besoin list(donc vous ne bénéficiez pas d'une itération paresseuse), car os.scandirutilise des API fournies par le système d'exploitation qui vous donnent les is_fileinformations gratuitement pendant l'itération. , pas par fichier aller - retour vers le disque statdu tout (sous Windows, les DirEntrys vous obtenez complète statinformation gratuitement, sur les systèmes * NIX il doit statpour plus d' informations au - delà is_file, is_dir, etc., mais les DirEntrycaches sur la première statpour des raisons pratiques).
ShadowRanger
1
Vous pouvez également utiliser entry.namepour obtenir uniquement le nom du fichier ou entry.pathpour obtenir son chemin complet. Plus d'os.path.join () partout.
user136036
56
Notes préliminaires
Bien qu'il y ait une différenciation claire entre les termes de fichier et de répertoire dans le texte de la question, certains peuvent affirmer que les répertoires sont en fait des fichiers spéciaux
La déclaration: " tous les fichiers d'un répertoire " peut être interprétée de deux manières:
Tous les descendants directs (ou niveau 1) uniquement
Tous les descendants de l'arborescence complète des répertoires (y compris ceux des sous-répertoires)
Lorsque la question a été posée, j'imagine que Python 2 était la version LTS , mais les exemples de code seront exécutés par Python 3 ( .5 ) (je les garderai aussi conformes que possible à Python 2 ; aussi, tout code appartenant à Python que je vais publier est de la v3.5.4 - sauf indication contraire). Cela a des conséquences liées à un autre mot-clé dans la question: " ajoutez-les dans une liste ":
En pré versions Python 2.2 , les séquences (itérables) étaient principalement représentées par des listes (tuples, sets, ...)
En Python 2.2 , le concept de générateur ( [Python.Wiki]: Generators ) - avec l'aimable autorisation de [Python 3]: la déclaration de rendement ) - a été introduit. Au fil du temps, les homologues du générateur ont commencé à apparaître pour les fonctions qui retournaient / fonctionnaient avec des listes
En Python 3 , le générateur est le comportement par défaut
Je ne sais pas si le retour d'une liste est toujours obligatoire (ou un générateur ferait de même), mais le passage d'un générateur au constructeur de liste en créera une liste (et la consommera également). L'exemple ci-dessous illustre les différences sur [Python 3]: map ( fonction, itérable, ... )
>>>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'>)
Les exemples seront basés sur un répertoire appelé root_dir avec la structure suivante (cet exemple est pour Win , mais j'utilise également la même arborescence sur Lnx ):
Renvoie une liste contenant les noms des entrées du répertoire donnés par path. La liste est dans un ordre arbitraire et ne comprend pas les entrées spéciales '.'et '..'...
>>>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 exemple plus élaboré ( 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()
Remarques :
Il existe deux implémentations:
Celui qui utilise des générateurs (bien sûr ici cela semble inutile, puisque je convertis immédiatement le résultat en liste)
Le classique (noms de fonctions se terminant par _old )
La récursivité est utilisée (pour entrer dans les sous-répertoires)
Pour chaque implémentation, il existe deux fonctions:
Celui qui commence par un trait de soulignement ( _ ): "privé" (ne doit pas être appelé directement) - qui fait tout le travail
Le public (wrapper sur le précédent): il supprime simplement le chemin initial (si nécessaire) des entrées retournées. C'est une implémentation moche, mais c'est la seule idée avec laquelle je pourrais venir à ce stade
En termes de performances, les générateurs sont généralement un peu plus rapides (considérant à la fois la création et l' itération ), mais je ne les ai pas testés dans les fonctions récursives, et j'itère également à l'intérieur de la fonction par rapport aux générateurs internes - je ne sais pas comment les performances amical est que
Jouez avec les arguments pour obtenir des résultats différents
Sortie :
(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']
Renvoie un itérateur d' objets os.DirEntry correspondant aux entrées du répertoire données par path . Les entrées sont dans un ordre arbitraire ont produit, et les entrées spéciales '.'et '..'ne sont pas inclus.
L'utilisation de scandir () au lieu de listdir () peut augmenter considérablement les performances du code qui nécessite également des informations sur le type ou l'attribut de fichier, car les objets os.DirEntry exposent ces informations si le système d'exploitation les fournit lors de l'analyse d'un répertoire. Toutes les méthodes os.DirEntry peuvent effectuer un appel système, mais is_dir () et is_file () nécessitent généralement un appel système uniquement pour les liens symboliques; os.DirEntry.stat () nécessite toujours un appel système sous Unix mais n'en requiert qu'un pour les liens symboliques sous 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
Remarques :
C'est similaire à os.listdir
Mais il est également plus flexible (et offre plus de fonctionnalités), plus de Python ic (et dans certains cas, plus rapide)
Générez les noms de fichiers dans une arborescence de répertoires en parcourant l'arborescence de haut en bas ou de bas en haut. Pour chaque répertoire dans l'arbre dont la racine répertoire haut (y compris haut lui - même), il donne un 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',[],[])
Remarques :
Sous les scènes, il utilise os.scandir ( os.listdirsur les anciennes versions)
Il fait le gros du travail en se reproduisant dans les sous-dossiers
Renvoie une liste éventuellement vide de noms de chemins correspondant à chemin d'accès , qui doit être une chaîne contenant une spécification de chemin. chemin peut être absolu (comme /usr/src/Python-1.5/Makefile) ou relatif (comme ../../Tools/*/*.gif), et peut contenir des caractères génériques de style shell. Les liens symboliques brisés sont inclus dans les résultats (comme dans le shell). ... Modifié dans la version 3.5 : Prise en charge des globes récursifs à l'aide de « **».
>>>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
Remarques :
Les usages os.listdir
Pour les grands arbres (surtout si récursif est activé ), l' iglob est préféré
Permet un filtrage avancé basé sur le nom (en raison du caractère générique)
>>>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']
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 est une bibliothèque de fonctions étrangère pour Python. Il fournit des types de données compatibles C et permet d'appeler des fonctions dans des DLL ou des bibliothèques partagées. Il peut être utilisé pour envelopper ces bibliothèques en Python pur.
LinuxDirent64 est la représentation ctypes de struct dirent64 de [man7]: dirent.h (0P) (tout comme les constantes DT_ ) de ma machine: Ubtu 16 x64 ( 4.10.0-40-generic et libc6-dev: amd64 ). Sur d'autres versions / versions, la définition de la structure peut différer, et si c'est le cas, l' alias ctypes doit être mis à jour, sinon cela produira un comportement indéfini
Il renvoie des données dans le os.walk format. Je n'ai pas pris la peine de le rendre récursif, mais à partir du code existant, ce serait une tâche assez banale
Tout est également faisable sur Win , les données (bibliothèques, fonctions, structures, constantes, ...) diffèrent
Sortie :
[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']]
Récupère une liste de noms de fichiers correspondants à l'aide de l'API Windows Unicode. Une interface vers les fonctions de fermeture de l'API FindFirstFileW / FindNextFileW / Find.
>>>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']
Le lien de documentation est de ActiveState , car je n'ai trouvé aucune documentation officielle PyWin32
Installez un (autre) paquet tiers qui fait l'affaire
Très probablement, s'appuiera sur l'un (ou plusieurs) des éléments ci-dessus (peut-être avec de légères personnalisations)
Remarques :
Le code est censé être portable (sauf les endroits qui ciblent une zone spécifique - qui sont marqués) ou croisés:
Plate-forme ( Nix , Win ,)
Version Python (2, 3,)
Plusieurs styles de chemin (absolu, apparenté) ont été utilisés dans les variantes ci-dessus, pour illustrer le fait que les "outils" utilisés sont flexibles dans cette direction.
_get_dir_content (à partir du point # 1. ) peut être implémenté en utilisant n'importe laquelle de ces approches (certaines nécessiteront plus de travail et d'autres moins)
Un filtrage avancé (au lieu de simplement fichier vs dir) pourrait être fait: par exemple, l' argument include_folders pourrait être remplacé par un autre (par exemple filter_func ) qui serait une fonction qui prend un chemin en argument:filter_func=lambda x: True (cela ne supprime pas n'importe quoi) et à l'intérieur de _get_dir_content quelque chose comme: if not filter_func(entry_with_path): continue(si la fonction échoue pour une entrée, elle sera ignorée), mais plus le code devient complexe, plus il faudra de temps pour l'exécuter
Nota bene! Puisque la récursivité est utilisée, je dois mentionner que j'ai fait des tests sur mon ordinateur portable ( Win 10 x64 ), totalement sans rapport avec ce problème, et lorsque le niveau de récursivité atteignait des valeurs quelque part dans la plage ( 990 .. 1000) ( recursionlimit - 1000 (par défaut)), j'ai obtenu StackOverflow :). Si l'arborescence de répertoires dépasse cette limite (je ne suis pas un expert FS , donc je ne sais pas si c'est même possible), cela pourrait être un problème.
Je dois également mentionner que je n'ai pas essayé d'augmenter la limite de récursivité car je n'ai aucune expérience dans le domaine (combien puis-je l'augmenter avant d'avoir à augmenter également la pile à OSniveau), mais en théorie, il y aura toujours la possibilité d'échec, si la profondeur dir est supérieure à la limite de récursivité la plus élevée possible (sur cette machine)
Les exemples de code sont uniquement à des fins de démonstration. Cela signifie que je n'ai pas pris en compte la gestion des erreurs (je ne pense pas qu'il y ait de bloc try / except / else / finally ), donc le code n'est pas robuste (la raison est: pour le garder aussi simple et court que possible ). Pour la production , la gestion des erreurs doit également être ajoutée
Autres approches:
Utiliser Python uniquement comme wrapper
Tout se fait en utilisant une autre technologie
Cette technologie est invoquée depuis Python
La saveur la plus célèbre que je connaisse est ce que j'appelle l' approche de l' administrateur système :
Utilisez Python (ou n'importe quel langage de programmation d'ailleurs) pour exécuter des commandes shell (et analyser leurs sorties)
Certains considèrent cela comme un hack soigné
Je le considère plus comme une solution de contournement boiteuse ( gainarie ), car l'action en soi est effectuée à partir du shell ( cmd dans ce cas), et n'a donc rien à voir avec Python .
Le filtrage ( grep/ findstr) ou le formatage de sortie pourrait être fait des deux côtés, mais je ne vais pas insister là-dessus. Aussi, j'ai délibérément utilisé os.systemau lieu de subprocess.Popen.
En général, cette approche est à éviter, car si certains formats de sortie de commande diffèrent légèrement entre les versions / versions du système d'exploitation , le code d'analyse doit également être adapté; sans parler des différences entre les paramètres régionaux).
J'ai vraiment aimé la réponse d'Adamk , suggérant que vous l' utilisiezglob() , à partir du module du même nom. Cela vous permet d'avoir une correspondance de motifs avec *s.
Mais comme d'autres personnes l'ont souligné dans les commentaires, glob()peuvent se tromper en raison de directions incohérentes. Pour vous aider, je vous suggère d'utiliser lejoin()expanduser() fonctions et dans le os.pathmodule, et peut-être legetcwd() fonction dans leos module.
À titre d'exemples:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
Ce qui précède est terrible - le chemin a été codé en dur et ne fonctionnera que sur Windows entre le nom du lecteur et le \ s en dur dans le chemin.
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'))
Ce qui précède fonctionne mieux, mais il repose sur le nom du dossier Usersqui se trouve souvent sur Windows et pas si souvent sur d'autres systèmes d'exploitation. Il repose également sur l'utilisateur ayant un nom spécifique,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'))
Cela fonctionne parfaitement sur toutes les plateformes.
Un autre excellent exemple qui fonctionne parfaitement sur toutes les plateformes et fait quelque chose d'un peu différent:
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'))
J'espère que ces exemples vous aideront à voir la puissance de quelques-unes des fonctions que vous pouvez trouver dans les modules de bibliothèque Python standard.
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
Pour de meilleurs résultats, vous pouvez utiliser la listdir()méthodeos module avec un générateur (un générateur est un itérateur puissant qui garde son état, vous vous souvenez?). Le code suivant fonctionne correctement avec les deux versions: Python 2 et Python 3.
Voici un code:
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)
La listdir()méthode renvoie la liste des entrées pour le répertoire donné. La méthode os.path.isfile()retourne Truesi l'entrée donnée est un fichier. L' yieldopérateur quitte la fonction mais conserve son état actuel et ne renvoie que le nom de l'entrée détectée sous forme de fichier. Tout ce qui précède nous permet de boucler sur la fonction du générateur.
Remarque: os.path.abspath(f)serait un substitut un peu moins cher os.path.join(os.getcwd(),f).
ShadowRanger
Je serais encore plus efficace si vous commenciez par cwd = os.path.abspath('.'), puis utilisé à la cwdplace de '.'et os.getcwd()tout au long pour éviter des charges d'appels système redondants.
La même chose peut être réalisée en une seule ligne avec pathlib:filter(Path.is_file, Path().rglob('*'))
Georgy
9
Un sage enseignant m'a dit une fois que:
Lorsqu'il existe plusieurs façons établies de faire quelque chose, aucune n'est bonne pour tous les cas.
J'ajouterai donc une solution pour un sous - ensemble du problème: bien souvent, nous voulons seulement vérifier si un fichier correspond à une chaîne de début et une chaîne de fin, sans entrer dans les sous-répertoires. Nous aimerions donc une fonction qui retourne une liste de noms de fichiers, comme:
Si vous souhaitez d'abord déclarer deux fonctions, cela peut être fait:
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)]
Cette solution pourrait être facilement généralisée avec des expressions régulières (et vous voudrez peut-être ajouter un patternargument, si vous ne voulez pas que vos modèles restent toujours au début ou à la fin du nom de fichier).
Une autre variante très lisible pour Python 3.4+ utilise pathlib.Path.glob:
from pathlib importPath
folder ='/foo'[f for f inPath(folder).glob('*')if f.is_file()]
Il est simple de le rendre plus spécifique, par exemple, ne recherchez que les fichiers source Python qui ne sont pas des liens symboliques, également dans tous les sous-répertoires:
[f for f inPath(folder).glob('**/*.py')ifnot f.is_symlink()]
Voici ma fonction polyvalente pour cela. Il retourne une liste de chemins de fichiers plutôt que des noms de fichiers car j'ai trouvé que c'était plus utile. Il a quelques arguments facultatifs qui le rendent polyvalent. Par exemple, je l'utilise souvent avec des arguments comme pattern='*.txt'ou 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)]
Je vais fournir un exemple d'un liner où le chemin source et le type de fichier peuvent être fournis en entrée. Le code renvoie une liste de noms de fichiers avec l'extension csv. Utilisez . au cas où tous les fichiers doivent être retournés. Cela balaye également récursivement les sous-répertoires.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modifiez les extensions de fichier et le chemin source selon vos besoins.
Si vous allez utiliser glob, utilisez simplement glob('**/*.csv', recursive=True). Pas besoin de combiner cela avec os.walk()pour recurse ( recursiveet **sont pris en charge depuis Python 3.5).
Réponses:
os.listdir()
vous obtiendra tout ce qui est dans un répertoire - fichiers et répertoires .Si vous voulez seulement des fichiers, vous pouvez soit filtrer cela en utilisant
os.path
:ou vous pouvez utiliser
os.walk()
qui donne deux listes pour chaque répertoire qu'il visite - division en fichiers et répertoires pour vous. Si vous ne voulez que le répertoire supérieur, vous pouvez simplement casser la première fois qu'il donnela source
(_, _, filenames) = walk(mypath).next()
(si vous êtes sûr que la marche renverra au moins une valeur, ce qu'elle devrait.)f.extend(filenames)
n'est pas réellement équivalent àf = f + filenames
.extend
modifieraf
sur place, tandis que l'ajout crée une nouvelle liste dans un nouvel emplacement de mémoire. Cela signifieextend
est généralement plus efficace que+
, mais cela peut parfois prêter à confusion si plusieurs objets contiennent des références à la liste. Enfin, il convient de noter que celaf += filenames
équivaut àf.extend(filenames)
, nonf = f + filenames
._, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Je préfère utiliser le
glob
module, car il fait la correspondance et l'expansion des modèles.Il renverra une liste avec les fichiers interrogés:
la source
/home/user/foo/bar/hello.txt
, si en cours d'exécution dans le répertoirefoo
, leglob("bar/*.txt")
retournebar/hello.txt
. Il y a des cas où vous voulez en fait le chemin complet (c'est-à-dire absolu); pour ces cas, voir stackoverflow.com/questions/51520/…glob.glob("*")
aurait.x=glob.glob("../train/*.png")
me donnera un tableau de mes chemins, tant que je connais le nom du dossier. Trop cool!Comment obtenir tous les fichiers (et répertoires) dans le répertoire courant (Python 3)
Voici des méthodes simples pour récupérer uniquement les fichiers dans le répertoire en cours, en utilisant
os
et lalistdir()
fonction, en Python 3. Une exploration plus approfondie, montrera comment retourner les dossiers dans le répertoire, mais vous n'aurez pas le fichier dans le sous-répertoire, pour cela vous peut utiliser la marche - discuté plus tard).J'ai trouvé glob plus facile de sélectionner le fichier du même type ou avec quelque chose en commun. Regardez l'exemple suivant:
La fonction renvoie une liste de l'extension donnée (.txt, .docx ecc.) Dans l'argument
La fonction retourne maintenant une liste de fichiers correspondant à la chaîne que vous passez en argument
production
Comme vous l'avez remarqué, vous n'avez pas le chemin complet du fichier dans le code ci-dessus. Si vous devez avoir le chemin absolu, vous pouvez utiliser une autre fonction du
os.path
module appelé_getfullpathname
, en plaçant le fichier dont vous obtenezos.listdir()
comme argument. Il existe d'autres façons d'avoir le chemin complet, comme nous le verrons plus tard (j'ai remplacé, comme suggéré par mexmex, _getfullpathname avecabspath
).Je trouve cela très utile pour trouver des choses dans de nombreux répertoires, et cela m'a aidé à trouver un fichier dont je ne me souvenais pas du nom:
En Python 2, si vous voulez la liste des fichiers dans le répertoire courant, vous devez donner l'argument comme '.' ou os.getcwd () dans la méthode os.listdir.
Si j'ai besoin du chemin absolu des fichiers:
Avec
list comprehension
:Vous pouvez également utiliser
pathlib.Path()
au lieu depathlib.Path(".")
Dans cet exemple, nous recherchons le nombre de fichiers inclus dans tout le répertoire et ses sous-répertoires.
Un script pour mettre de l'ordre dans votre ordinateur en trouvant tous les fichiers d'un type (par défaut: pptx) et en les copiant dans un nouveau dossier.
Dans le cas où vous souhaitez créer un fichier txt avec tous les noms de fichiers:
Avec cette fonction, vous pouvez créer un fichier txt qui aura le nom d'un type de fichier que vous recherchez (ex. Pngfile.txt) avec tout le chemin complet de tous les fichiers de ce type. Cela peut être utile parfois, je pense.
la source
renverra une liste de tous les fichiers et répertoires dans "somedirectory".
la source
glob.glob
os.listdir()
renvoie toujours de simples noms de fichiers (pas des chemins relatifs). Ce quiglob.glob()
retourne est déterminé par le format de chemin du modèle d'entrée.Une solution en ligne pour obtenir uniquement la liste des fichiers (pas de sous-répertoires):
ou chemins absolus:
la source
import os
. Semble moins concis qu'àglob()
moi.glob()
le traiterait comme un fichier. Votre méthode le traiterait comme un répertoire.Obtention de chemins de fichiers complets à partir d'un répertoire et de tous ses sous-répertoires
print full_file_paths
qui imprimera la liste:['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Si vous le souhaitez, vous pouvez ouvrir et lire le contenu, ou vous concentrer uniquement sur les fichiers avec l'extension ".dat" comme dans le code ci-dessous:
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
la source
Depuis la version 3.4, il existe des itérateurs intégrés pour cela qui sont beaucoup plus efficaces que
os.listdir()
:pathlib
: Nouveau dans la version 3.4.Selon PEP 428 , l'objectif de la
pathlib
bibliothèque est de fournir une hiérarchie simple de classes pour gérer les chemins de système de fichiers et les opérations courantes que les utilisateurs effectuent sur eux.os.scandir()
: Nouveau dans la version 3.5.Notez que
os.walk()
utiliseos.scandir()
au lieu deos.listdir()
version 3.5, et sa vitesse a été augmentée de 2 à 20 fois selon le PEP 471 .Permettez-moi également de lire le commentaire de ShadowRanger ci-dessous.
la source
list
. Pourrait utiliser à lap.name
place du premierp
alternativement si vous préférez.pathlib.Path()
instances car elles ont de nombreuses méthodes utiles que je ne voudrais pas gaspiller. Vous pouvez également faire appelstr(p)
à eux pour les noms de chemin.os.scandir
solution sera plus efficaceos.listdir
qu'avec uneos.path.is_file
vérification ou similaire, même si vous en avez besoinlist
(donc vous ne bénéficiez pas d'une itération paresseuse), caros.scandir
utilise des API fournies par le système d'exploitation qui vous donnent lesis_file
informations gratuitement pendant l'itération. , pas par fichier aller - retour vers le disquestat
du tout (sous Windows, lesDirEntry
s vous obtenez complètestat
information gratuitement, sur les systèmes * NIX il doitstat
pour plus d' informations au - delàis_file
,is_dir
, etc., mais lesDirEntry
caches sur la premièrestat
pour des raisons pratiques).entry.name
pour obtenir uniquement le nom du fichier ouentry.path
pour obtenir son chemin complet. Plus d'os.path.join () partout.Notes préliminaires
Lorsque la question a été posée, j'imagine que Python 2 était la version LTS , mais les exemples de code seront exécutés par Python 3 ( .5 ) (je les garderai aussi conformes que possible à Python 2 ; aussi, tout code appartenant à Python que je vais publier est de la v3.5.4 - sauf indication contraire). Cela a des conséquences liées à un autre mot-clé dans la question: " ajoutez-les dans une liste ":
Les exemples seront basés sur un répertoire appelé root_dir avec la structure suivante (cet exemple est pour Win , mais j'utilise également la même arborescence sur Lnx ):
Solutions
Approches programmatiques:
[Python 3]: os. listdir ( path = '.' )
Un exemple plus élaboré ( code_os_listdir.py ):
Remarques :
Sortie :
[Python 3]: os. scandir ( path = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )
Remarques :
os.listdir
[Python 3]: os. marcher ( top, topdown = True, onerror = None, followlinks = False )
Remarques :
os.scandir
(os.listdir
sur les anciennes versions)[Python 3]: glob. glob ( nom de chemin, *, récursif = Faux ) ( [Python 3]: glob. iglob ( nom de chemin, *, récursif = Faux) ) )
Remarques :
os.listdir
[Python 3]: class pathlib. Path ( * pathsegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )
Remarques :
[Python 2]: dircache.listdir (chemin) ( Python 2 uniquement)
os.listdir
avec mise en cache[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) via [Python 3]: ctypes - Une bibliothèque de fonctions étrangères pour Python ( spécifique POSIX )
code_ctypes.py :
Remarques :
os.walk
format. Je n'ai pas pris la peine de le rendre récursif, mais à partir du code existant, ce serait une tâche assez banaleSortie :
[ActiveState.Docs]: win32file.FindFilesW ( spécifique à Win )
Remarques :
win32file.FindFilesW
fait partie de [GitHub]: mhammond / pywin32 - Python pour Windows (pywin32) Extensions , qui est un wrapper Python sur WINAPI sRemarques :
Le code est censé être portable (sauf les endroits qui ciblent une zone spécifique - qui sont marqués) ou croisés:
Plusieurs styles de chemin (absolu, apparenté) ont été utilisés dans les variantes ci-dessus, pour illustrer le fait que les "outils" utilisés sont flexibles dans cette direction.
os.listdir
etos.scandir
utilisez opendir / readdir / closedir ( [MS.Docs]: fonction FindFirstFileW / [MS.Docs]: fonction FindNextFileW / [MS.Docs]: fonction FindClose ) (via [GitHub]: python / cpython - (master) cpython / Modules / posixmodule.c )win32file.FindFilesW
utilise également ces fonctions ( spécifiques à Win ) (via [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / src / win32file.i )_get_dir_content (à partir du point # 1. ) peut être implémenté en utilisant n'importe laquelle de ces approches (certaines nécessiteront plus de travail et d'autres moins)
filter_func=lambda x: True
(cela ne supprime pas n'importe quoi) et à l'intérieur de _get_dir_content quelque chose comme:if not filter_func(entry_with_path): continue
(si la fonction échoue pour une entrée, elle sera ignorée), mais plus le code devient complexe, plus il faudra de temps pour l'exécuterNota bene! Puisque la récursivité est utilisée, je dois mentionner que j'ai fait des tests sur mon ordinateur portable ( Win 10 x64 ), totalement sans rapport avec ce problème, et lorsque le niveau de récursivité atteignait des valeurs quelque part dans la plage ( 990 .. 1000) ( recursionlimit - 1000 (par défaut)), j'ai obtenu StackOverflow :). Si l'arborescence de répertoires dépasse cette limite (je ne suis pas un expert FS , donc je ne sais pas si c'est même possible), cela pourrait être un problème.
Je dois également mentionner que je n'ai pas essayé d'augmenter la limite de récursivité car je n'ai aucune expérience dans le domaine (combien puis-je l'augmenter avant d'avoir à augmenter également la pile à OSniveau), mais en théorie, il y aura toujours la possibilité d'échec, si la profondeur dir est supérieure à la limite de récursivité la plus élevée possible (sur cette machine)
Les exemples de code sont uniquement à des fins de démonstration. Cela signifie que je n'ai pas pris en compte la gestion des erreurs (je ne pense pas qu'il y ait de bloc try / except / else / finally ), donc le code n'est pas robuste (la raison est: pour le garder aussi simple et court que possible ). Pour la production , la gestion des erreurs doit également être ajoutée
Autres approches:
Utiliser Python uniquement comme wrapper
La saveur la plus célèbre que je connaisse est ce que j'appelle l' approche de l' administrateur système :
grep
/findstr
) ou le formatage de sortie pourrait être fait des deux côtés, mais je ne vais pas insister là-dessus. Aussi, j'ai délibérément utiliséos.system
au lieu desubprocess.Popen
.En général, cette approche est à éviter, car si certains formats de sortie de commande diffèrent légèrement entre les versions / versions du système d'exploitation , le code d'analyse doit également être adapté; sans parler des différences entre les paramètres régionaux).
la source
J'ai vraiment aimé la réponse d'Adamk , suggérant que vous l' utilisiez
glob()
, à partir du module du même nom. Cela vous permet d'avoir une correspondance de motifs avec*
s.Mais comme d'autres personnes l'ont souligné dans les commentaires,
glob()
peuvent se tromper en raison de directions incohérentes. Pour vous aider, je vous suggère d'utiliser lejoin()
expanduser()
fonctions et dans leos.path
module, et peut-être legetcwd()
fonction dans leos
module.À titre d'exemples:
Ce qui précède est terrible - le chemin a été codé en dur et ne fonctionnera que sur Windows entre le nom du lecteur et le
\
s en dur dans le chemin.Ce qui précède fonctionne mieux, mais il repose sur le nom du dossier
Users
qui se trouve souvent sur Windows et pas si souvent sur d'autres systèmes d'exploitation. Il repose également sur l'utilisateur ayant un nom spécifique,admin
.Cela fonctionne parfaitement sur toutes les plateformes.
Un autre excellent exemple qui fonctionne parfaitement sur toutes les plateformes et fait quelque chose d'un peu différent:
J'espère que ces exemples vous aideront à voir la puissance de quelques-unes des fonctions que vous pouvez trouver dans les modules de bibliothèque Python standard.
la source
**
fonctionne aussi longtemps que vous le définissezrecursive = True
. Voir les documents ici: docs.python.org/3.5/library/glob.html#glob.globla source
Si vous recherchez une implémentation Python de find , voici une recette que j'utilise assez fréquemment:
J'en ai donc fait un paquet PyPI et il y a aussi un dépôt GitHub . J'espère que quelqu'un le trouve potentiellement utile pour ce code.
la source
Pour de meilleurs résultats, vous pouvez utiliser la
listdir()
méthodeos
module avec un générateur (un générateur est un itérateur puissant qui garde son état, vous vous souvenez?). Le code suivant fonctionne correctement avec les deux versions: Python 2 et Python 3.Voici un code:
La
listdir()
méthode renvoie la liste des entrées pour le répertoire donné. La méthodeos.path.isfile()
retourneTrue
si l'entrée donnée est un fichier. L'yield
opérateur quitte la fonction mais conserve son état actuel et ne renvoie que le nom de l'entrée détectée sous forme de fichier. Tout ce qui précède nous permet de boucler sur la fonction du générateur.la source
Renvoyer une liste de chemins de fichiers absolus, n'est pas récurrent dans les sous-répertoires
la source
os.path.abspath(f)
serait un substitut un peu moins cheros.path.join(os.getcwd(),f)
.cwd = os.path.abspath('.')
, puis utilisé à lacwd
place de'.'
etos.getcwd()
tout au long pour éviter des charges d'appels système redondants.Ici, j'utilise une structure récursive.
la source
pathlib
:filter(Path.is_file, Path().rglob('*'))
Un sage enseignant m'a dit une fois que:
J'ajouterai donc une solution pour un sous - ensemble du problème: bien souvent, nous voulons seulement vérifier si un fichier correspond à une chaîne de début et une chaîne de fin, sans entrer dans les sous-répertoires. Nous aimerions donc une fonction qui retourne une liste de noms de fichiers, comme:
Si vous souhaitez d'abord déclarer deux fonctions, cela peut être fait:
Cette solution pourrait être facilement généralisée avec des expressions régulières (et vous voudrez peut-être ajouter un
pattern
argument, si vous ne voulez pas que vos modèles restent toujours au début ou à la fin du nom de fichier).la source
Utilisation de générateurs
la source
Une autre variante très lisible pour Python 3.4+ utilise pathlib.Path.glob:
Il est simple de le rendre plus spécifique, par exemple, ne recherchez que les fichiers source Python qui ne sont pas des liens symboliques, également dans tous les sous-répertoires:
la source
Voici ma fonction polyvalente pour cela. Il retourne une liste de chemins de fichiers plutôt que des noms de fichiers car j'ai trouvé que c'était plus utile. Il a quelques arguments facultatifs qui le rendent polyvalent. Par exemple, je l'utilise souvent avec des arguments comme
pattern='*.txt'
ousubfolders=True
.la source
Je vais fournir un exemple d'un liner où le chemin source et le type de fichier peuvent être fournis en entrée. Le code renvoie une liste de noms de fichiers avec l'extension csv. Utilisez . au cas où tous les fichiers doivent être retournés. Cela balaye également récursivement les sous-répertoires.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modifiez les extensions de fichier et le chemin source selon vos besoins.
la source
glob
, utilisez simplementglob('**/*.csv', recursive=True)
. Pas besoin de combiner cela avecos.walk()
pour recurse (recursive
et**
sont pris en charge depuis Python 3.5).Pour python2: pip install rglob
la source
dircache est "obsolète depuis la version 2.6: le module dircache a été supprimé dans Python 3.0."
la source