web-dev-qa-db-fra.com

Itération dans les répertoires avec Python

Je dois parcourir les sous-répertoires d'un répertoire donné et rechercher des fichiers. Si je reçois un fichier, je dois l'ouvrir, modifier le contenu et le remplacer par mes propres lignes.

J'ai essayé ceci:

import os

rootdir ='C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        f=open(file,'r')
        lines=f.readlines()
        f.close()
        f=open(file,'w')
        for line in lines:
            newline = "No you are not"
            f.write(newline)
        f.close()

mais je reçois une erreur. Qu'est-ce que je fais mal?

126
Wolf

La marche à travers les répertoires fonctionne comme vous l'avez codé. Si vous remplacez le contenu de la boucle interne par une simple instruction print, vous pouvez voir que chaque fichier est trouvé:

import os
rootdir = 'C:/Users/sid/Desktop/test'

for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print os.path.join(subdir, file)

Si vous rencontrez toujours des erreurs lors de l'exécution de ce qui précède, veuillez fournir le message d'erreur.

255
ChrisProsser

Une autre façon de renvoyer tous les fichiers dans les sous-répertoires consiste à utiliser le module pathlib , introduit dans Python 3.4, qui fournit une approche orientée objet de la gestion des chemins de système de fichiers (Pathlib est également disponible sur Python 2.7 via le module pathlib2 sur PyPi ):

from pathlib import Path

rootdir = Path('C:/Users/sid/Desktop/test')
# Return a list of regular files only, not directories
file_list = [f for f in rootdir.glob('**/*') if f.is_file()]

# For absolute paths instead of relative the current dir
file_list = [f for f in rootdir.resolve().glob('**/*') if f.is_file()]

Depuis Python 3.5, le module glob prend également en charge la recherche de fichier récursive:

import os
from glob import iglob

rootdir_glob = 'C:/Users/sid/Desktop/test/**/*' # Note the added asterisks
# This will return absolute paths
file_list = [f for f in iglob('**/*', recursive=True) if os.path.isfile(f)]

Le file_list de l'une des approches ci-dessus peut être itéré sans la nécessité d'une boucle imbriquée:

for f in file_list:
    print(f) # Replace with desired operations
8
joelostblom

À partir de 2019 , glob.iglob(path/**, recursive=True) semble être la solution la plus Pythonic , c'est-à-dire:

import glob, os

for filename in glob.iglob('/pardadox-music/**', recursive=True):
    if os.path.isfile(filename): # filter dirs
        print(filename)

Sortie:

/pardadox-music/modules/her1.mod
/pardadox-music/modules/her2.mod
...

Remarques:
1 - glob.iglob

glob.iglob(pathname, recursive=False)

Renvoie un itérateur qui renvoie les mêmes valeurs que glob() sans les stocker tous en même temps.

2 - Si récursif est True, le motif '**' correspond à tous les fichiers et à zéro ou plus directories et subdirectories.

.

4
Pedro Lobito