331 votes

Python récursive dossier en lecture

J'ai un C++/Obj-C en arrière-plan et je suis dans la découverte de Python (été écrit environ une heure). Je suis en train d'écrire un script récursive de lire le contenu des fichiers texte dans une structure de dossier.

Le problème que j'ai c'est le code que j'ai écrit ne fonctionne que pour un dossier de profondeur. Je peux voir pourquoi dans le code (voir #hardcoded path- )), je ne sais pas comment je peux aller de l'avant avec Python depuis mon expérience avec elle, c'est seulement de nouvelles.

Voici ce que ma structure de répertoire ressemble à:

alt text

Le Code Python:

import os
import sys

rootdir = sys.argv[1]

for root, subFolders, files in os.walk(rootdir):

    for folder in subFolders:
        outfileName = rootdir + "/" + folder + "/py-outfile.txt" # hardcoded path
        folderOut = open( outfileName, 'w' )
        print "outfileName is " + outfileName

        for file in files:
            filePath = rootdir + '/' + file
            f = open( filePath, 'r' )
            toWrite = f.read()
            print "Writing '" + toWrite + "' to" + filePath
            folderOut.write( toWrite )
            f.close()

        folderOut.close()

462voto

AndiDog Points 28417

Assurez-vous que vous comprenez les trois valeurs de retour d' os.walk:

for root, subdirs, files in os.walk(rootdir):

a la signification suivante:

  • root: Chemin d'accès actuel qui est "traversé"
  • subdirs: Fichiers en root de type répertoire
  • files: Fichiers en root (pas en subdirs) de type autre que le répertoire

Et s'il vous plaît utiliser os.path.join au lieu de concaténer avec un slash! Votre problème est - filePath = rootdir + '/' + file - vous devez concaténer le "marché" dossier à la place du premier dossier. De sorte que doit être filePath = os.path.join(root, file). BTW "fichier" est un builtin, de sorte que vous n'avez pas l'habitude de l'utiliser comme nom de variable.

Un autre problème sont vos boucles, qui devrait être comme ceci, par exemple:

import os
import sys

walk_dir = sys.argv[1]

print('walk_dir = ' + walk_dir)

# If your current working directory may change during script execution, it's recommended to
# immediately convert program arguments to an absolute path. Then the variable root below will
# be an absolute path as well. Example:
# walk_dir = os.path.abspath(walk_dir)
print('walk_dir (absolute) = ' + os.path.abspath(walk_dir))

for root, subdirs, files in os.walk(walk_dir):
    print('--\nroot = ' + root)
    list_file_path = os.path.join(root, 'my-directory-list.txt')
    print('list_file_path = ' + list_file_path)

    with open(list_file_path, 'wb') as list_file:
        for subdir in subdirs:
            print('\t- subdirectory ' + subdir)

        for filename in files:
            file_path = os.path.join(root, filename)

            print('\t- file %s (full path: %s)' % (filename, file_path))

            with open(file_path, 'rb') as f:
                f_content = f.read()
                list_file.write(('The file %s contains:\n' % filename).encode('utf-8'))
                list_file.write(f_content)
                list_file.write(b'\n')

Si vous ne le saviez pas, l' with déclaration de fichiers est un raccourci:

with open('filename', 'rb') as f:
    dosomething()

# is effectively the same as

f = open('filename', 'rb')
try:
    dosomething()
finally:
    f.close()

44voto

Clément Points 4224

D'accord avec Dave Webb, os.walk permettra d'obtenir un point pour chaque répertoire dans l'arborescence. Le fait est que vous n'avez tout simplement pas de soins sur subFolders.

Ce Code devrait fonctionner:

import os
import sys

rootdir = sys.argv[1]

for folder, subs, files in os.walk(rootdir):
    with open(os.path.join(folder, 'python-outfile.txt'), 'w') as dest:
        for filename in files:
            with open(os.path.join(folder, filename), 'r') as src:
                dest.write(src.read())

3voto

ghostdog74 Points 86060

utiliser os.path.join() de construction des chemins d'accès - C'est plus lisible:

import os
import sys
rootdir = sys.argv[1]
for root, subFolders, files in os.walk(rootdir):
    for folder in subFolders:
        outfileName = os.path.join(root,folder,"py-outfile.txt")
        folderOut = open( outfileName, 'w' )
        print "outfileName is " + outfileName
        for file in files:
            filePath = os.path.join(root,file)
            toWrite = open( filePath).read()
            print "Writing '" + toWrite + "' to" + filePath
            folderOut.write( toWrite )
        folderOut.close()

1voto

b1r3k Points 181

os.walk ne récursive de marche par défaut. Pour chaque dir, à partir de la racine, il donne un 3-tuple (dirpath, dirnames, les noms de fichiers)

from os import walk
from os.path import splitext, join

def select_files(root, files):
    """
    simple logic here to filter out interesting files
    .py files in this example
    """

    selected_files = []

    for file in files:
        #do concatenation here to get full path 
        full_path = join(root, file)
        ext = splitext(file)[1]

        if ext == ".py":
            selected_files.append(full_path)

    return selected_files

def build_recursive_dir_tree(path):
    """
    path    -    where to begin folder scan
    """
    selected_files = []

    for root, dirs, files in walk(path):
        selected_files += select_files(root, files)

    return selected_files

0voto

Dave Webb Points 90034

Je pense que le problème, c'est que vous n'êtes pas le traitement de la sortie de l' os.walk correctement.

Tout d'abord, modifiez:

filePath = rootdir + '/' + file

pour:

filePath = root + '/' + file

rootdir est votre fixe répertoire de départ; root est un annuaire retourné par os.walk.

Deuxièmement, vous n'avez pas besoin de retrait de votre fichier de traitement de la boucle, comme il n'a pas de sens pour exécuter ce pour chaque sous-répertoire. Vous obtiendrez root pour chaque sous-répertoire. Vous n'avez pas besoin de traiter les sous-répertoires à la main, sauf si vous voulez faire quelque chose avec les répertoires eux-mêmes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X