Trouver tous les fichiers dans un répertoire avec l'extension .txt en Python

1043

Comment puis-je trouver tous les fichiers dans un répertoire ayant l'extension .txten python?

usertest
la source

Réponses:

2359

Vous pouvez utiliser glob:

import glob, os
os.chdir("/mydir")
for file in glob.glob("*.txt"):
    print(file)

ou simplement os.listdir:

import os
for file in os.listdir("/mydir"):
    if file.endswith(".txt"):
        print(os.path.join("/mydir", file))

ou si vous souhaitez parcourir le répertoire, utilisez 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))
ghostdog74
la source
11
En utilisant la solution n ° 2, comment créer un fichier ou une liste avec ces informations?
Merlin
72
@ ghostdog74: À mon avis, il serait plus approprié d'écrire for file in fque pour for files in fpuisque ce qui est dans la variable est un nom de fichier unique. Encore mieux serait de changer les boucles fto files, puis les boucles for pourraient devenir for file in files.
martineau
46
@computermacgyver: Non, ce filen'est pas un mot réservé, juste le nom d'une fonction prédéfinie, il est donc tout à fait possible de l'utiliser comme nom de variable dans votre propre code. Bien qu'il soit vrai qu'en général, il faut éviter de telles collisions, filec'est un cas particulier car il n'y a presque jamais besoin de l'utiliser, il est donc souvent considéré comme une exception à la directive. Si vous ne voulez pas faire cela, PEP8 recommande d'ajouter un seul trait de soulignement à ces noms, c'est file_-à- dire que vous devez accepter est encore tout à fait lisible.
martineau
9
Merci, Martineau, vous avez absolument raison. J'ai sauté trop vite aux conclusions.
computermacgyver
40
Une manière plus pythonique pour # 2 peut être pour le fichier dans [f pour f dans os.listdir ('/ mydir') si f.endswith ('. Txt')]:
ozgur
247

Utilisez glob .

>>> import glob
>>> glob.glob('./*.txt')
['./outline.txt', './pip-log.txt', './test.txt', './testingvim.txt']
Muhammad Alkarouri
la source
Non seulement cela est facile, mais il est également insensible à la casse. (Au moins, il est sous Windows, comme il se doit. Je ne suis pas sûr des autres systèmes d'exploitation.)
Jon Coombs
35
Attention, globvous ne pouvez pas trouver de fichiers récursivement si votre python est inférieur à 3.5. plus d'informations
qun
la meilleure partie est que vous pouvez utiliser le test d'expression régulière * .txt
Alex Punnen
@JonCoombs non. Du moins pas sous Linux.
Karuhanga
157

Quelque chose comme ça devrait faire le travail

for root, dirs, files in os.walk(directory):
    for file in files:
        if file.endswith('.txt'):
            print file
Adam Byrtek
la source
73
+1 pour nommer vos variables root, dirs, filesau lieu de r, d, f. Beaucoup plus lisible.
Clément
27
Notez que ceci est sensible à la casse (ne correspondra pas à .TXT ou .Txt), donc vous voudrez probablement le faire si file.lower (). Endswith ('. Txt'):
Jon Coombs
1
votre réponse concerne le sous-répertoire.
Sam Liao
117

Quelque chose comme ça fonctionnera:

>>> 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']
Seth
la source
Comment enregistrer le chemin d'accès aux fichiers texte? ['path / euc-cn.txt', ... 'path / windows-950.txt']
IceQueeny
5
Vous pouvez utiliser os.path.joinsur chaque élément de text_files. Ça pourrait être quelque chose comme ça text_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.txt')].
Seth
55

Vous pouvez simplement utiliser pathlibs 1 :glob

import pathlib

list(pathlib.Path('your_directory').glob('*.txt'))

ou en boucle:

for txt_file in pathlib.Path('your_directory').glob('*.txt'):
    # do something with "txt_file"

Si vous le souhaitez récursif, vous pouvez utiliser .glob('**/*.txt)


1 Le pathlibmodule a été inclus dans la bibliothèque standard de python 3.4. Mais vous pouvez installer les ports arrière de ce module même sur les anciennes versions de Python (c'est-à-dire en utilisant condaou pip): pathlibet pathlib2.

MSeifert
la source
**/*.txtn'est pas pris en charge par les anciennes versions de python. J'ai donc résolu ce problème avec: foundfiles= subprocess.check_output("ls **/*.txt", shell=True) for foundfile in foundfiles.splitlines(): print foundfile
Roman
1
@Roman Oui, c'était juste une vitrine de ce qui pathlibpeut faire et j'ai déjà inclus les exigences de la version Python. :) Mais si votre approche n'a pas encore été publiée, pourquoi ne pas simplement l'ajouter comme autre réponse?
MSeifert
1
oui, poster une réponse m'aurait définitivement donné de meilleures possibilités de formatage. Je le poste - bas parce que je pense que c'est un endroit plus approprié pour cela.
Roman
5
Notez que vous pouvez également l'utiliser rglobsi vous souhaitez rechercher des éléments de manière récursive. Par exemple.rglob('*.txt')
Bram Vanroy
40
import os

path = 'mypath/path' 
files = os.listdir(path)

files_txt = [i for i in files if i.endswith('.txt')]
user3281344
la source
29

J'aime 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)

Ou avec des générateurs:

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)
Hughdbrown
la source
28

Voici d'autres versions du même qui produisent des résultats légèrement différents:

glob.iglob ()

import glob
for f in glob.iglob("/mydir/*/*.txt"): # generator, search immediate subdirectories 
    print f

glob.glob1 ()

print glob.glob1("/mydir", "*.tx?")  # literal_directory, basename_pattern

fnmatch.filter ()

import fnmatch, os
print fnmatch.filter(os.listdir("/mydir"), "*.tx?") # include dot-files
jfs
la source
3
Pour les curieux, glob1()est une fonction d'aide dans le globmodule qui n'est pas répertoriée dans la documentation Python. Il y a des commentaires en ligne décrivant ce qu'il fait dans le fichier source, voir .../Lib/glob.py.
martineau
1
@martineau: glob.glob1()n'est pas public mais il est disponible sur Python 2.4-2.7; 3.0-3.2; pypy; jython github.com/zed/test_glob1
jfs
1
Merci, ce sont de bonnes informations supplémentaires à avoir pour décider d'utiliser une fonction privée non documentée dans un module. ;-) Voici un peu plus. La version Python 2.7 ne fait que 12 lignes et semble pouvoir être facilement extraite du globmodule.
martineau
21

path.py est une autre alternative: 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
Anuvrat Parashar
la source
Cool, il accepte également l'expression régulière dans le motif. J'utilise for f in p.walk(pattern='*.txt')go through every subfolders
Kostanos
1
Ya il y a aussi pathlib. Vous pouvez faire quelque chose comme: list(p.glob('**/*.py'))
user2233949
15

Python v3.5 +

Méthode rapide utilisant os.scandir dans une fonction récursive. Recherche tous les fichiers avec une extension spécifiée dans le dossier et les sous-dossiers.

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)

Mise à jour avril 2019

Si vous recherchez dans des répertoires contenant 10 000 fichiers, l'ajout à une liste devient inefficace. «Céder» les résultats est une meilleure solution. J'ai également inclus une fonction pour convertir la sortie en un Pandas Dataframe.

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)
DougR
la source
14

Python a tous les outils pour le faire:

import os

the_dir = 'the_dir_that_want_to_search_in'
all_txt_files = filter(lambda x: x.endswith('.txt'), os.listdir(the_dir))
Xxxo
la source
1
Si vous voulez que all_txt_files soit une liste:all_txt_files = list(filter(lambda x: x.endswith('.txt'), os.listdir(the_dir)))
Ena
12

Pour obtenir tous les noms de fichiers '.txt' dans le dossier 'dataPath' sous forme de liste de manière 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
ewalel
la source
12

Essayez ceci, cela trouvera tous vos fichiers récursivement:

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)
mayank
la source
pas avec version récursive (double étoile:) **. Uniquement disponible en python 3. Ce que je n'aime pas, c'est la chdirpartie. Pas besoin de çà.
Jean-François Fabre
2
eh bien, vous pouvez utiliser la bibliothèque os pour joindre le chemin, par exemple, filepath = os.path.join('wallpaper')puis l'utiliser comme glob.glob(filepath+"**/*.psd", recursive = True), ce qui donnerait le même résultat.
Mitalee Rao
8
import os
import sys 

if len(sys.argv)==2:
    print('no params')
    sys.exit(1)

dir = sys.argv[1]
mask= sys.argv[2]

files = os.listdir(dir); 

res = filter(lambda x: x.endswith(mask), files); 

print res
mrgloom
la source
8

J'ai fait un test (Python 3.6.4, W7x64) pour voir quelle solution est la plus rapide pour un dossier, pas de sous-répertoires, pour obtenir une liste de chemins de fichiers complets pour les fichiers avec une extension spécifique.

Pour faire court, cette tâche os.listdir()est la plus rapide et 1,7 fois plus rapide que la suivante: os.walk()(avec une pause!), 2,7 fois plus rapide, 3,2 fois plus rapide pathlibque os.scandir()et 3,3 fois plus rapide que glob.
N'oubliez pas que ces résultats changeront lorsque vous aurez besoin de résultats récursifs. Si vous copiez / collez une méthode ci-dessous, veuillez ajouter un .lower () sinon .EXT ne sera pas trouvé lors de la recherche de .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))

Résultats:

# Python 3.6.4
0.431
0.515
0.161
0.548
0.537
0.274
user136036
la source
La documentation de Python 3.6.5 indique: La fonction os.scandir () renvoie des entrées de répertoire avec des informations d'attribut de fichier, offrant de meilleures performances [que os.listdir ()] pour de nombreux cas d'utilisation courants.
Bill Oldroyd
Il me manque l'étendue de mise à l'échelle de ce test combien de fichiers avez-vous utilisé dans ce test? comment se comparent-ils si vous augmentez / diminuez le nombre?
N4ppeL
5

Ce code me simplifie la vie.

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)
praba230890
la source
5

Pour obtenir un tableau de noms de fichiers ".txt" à partir d'un dossier appelé "data" dans le même répertoire, j'utilise généralement cette simple ligne de code:

import os
fileNames = [fileName for fileName in os.listdir("data") if fileName.endswith(".txt")]
Kamen Tsvetkov
la source
3

Je vous suggère d'utiliser fnmatch et la méthode supérieure. De cette façon, vous pouvez trouver l'un des éléments suivants:

  1. Nom. txt ;
  2. Nom. TXT ;
  3. Nom. SMS

.

import fnmatch
import os

    for file in os.listdir("/Users/Johnny/Desktop/MyTXTfolder"):
        if fnmatch.fnmatch(file.upper(), '*.TXT'):
            print(file)
Nicolaesse
la source
3

En voici un avec extend()

types = ('*.jpg', '*.png')
images_list = []
for files in types:
    images_list.extend(glob.glob(os.path.join(path, files)))
Efreeto
la source
Ne pas utiliser avec .txt:)
Efreeto
2

Solution fonctionnelle avec sous-répertoires:

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"))))
Adam Chrapkowski
la source
15
Est-ce ce code que vous voudriez conserver à long terme?
Simeon Visser du
2

Dans le cas où le dossier contient beaucoup de fichiers ou si la mémoire est une contrainte, pensez à utiliser des générateurs:

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

Option A: répéter

for f in yield_files_with_extensions('.', '.txt'): 
    print(f)

Option B: Obtenez tout

files = [f for f in yield_files_with_extensions('.', '.txt')]
tashuhka
la source
2

Une solution copiable-collable similaire à celle de 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
Martin Thoma
la source
1

utilisez le module Python OS pour rechercher des fichiers avec une extension spécifique.

l'exemple simple est ici:

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
Rajiv Sharma
la source
0

De nombreux utilisateurs ont répondu avec des os.walkréponses, qui incluent tous les fichiers mais aussi tous les répertoires et sous-répertoires et leurs fichiers.

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)

Ou pour un seul où vous n'avez pas besoin d'un générateur:

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)

Si vous allez utiliser des correspondances pour autre chose, vous pouvez en faire une liste plutôt qu'une expression de générateur:

    matches = [f for f in dirfiles if f.endswith(ext)]
kfsone
la source
0

Une méthode simple en utilisant la forboucle:

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")

Bien que cela puisse être généralisé.

BoRRis
la source
très pythonique de vérifier une extension. Pas sûr aussi. Et si le nom est trop court? et pourquoi utiliser une liste de caractères et non des chaînes?
Jean-François Fabre