J'ai un arrière-plan C++/Obj-C et je viens de découvrir Python (en train de l'écrire depuis environ une heure) .
Le problème que j'ai est que le code que j'ai écrit ne fonctionnera que pour un seul dossier. Je peux voir pourquoi dans le code (voir #hardcoded path
), je ne sais tout simplement pas comment je peux avancer avec Python car mon expérience avec ce dernier n’est que nouvelle.
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()
Assurez-vous de bien comprendre les trois valeurs de retour de os.walk
:
for root, subdirs, files in os.walk(rootdir):
a la signification suivante:
root
: chemin actuel "parcourant"subdirs
: Fichiers dans root
du type répertoirefiles
: Fichiers dans root
(pas dans subdirs
) de type autre que répertoireEt s'il vous plaît utilisez os.path.join
au lieu de concaténer avec une barre oblique! Votre problème est filePath = rootdir + '/' + file
- vous devez concaténer le dossier actuellement "parcouru" au lieu du dossier le plus haut. Donc, cela doit être filePath = os.path.join(root, file)
. BTW "fichier" est intégré, vous ne l'utilisez donc pas normalement comme nom de variable.
Un autre problème concerne vos boucles, qui devraient ê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'instruction with
pour les 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()
Si vous utilisez Python 3.5 ou supérieur, vous pouvez le faire en 1 ligne.
import glob
for filename in glob.iglob(root_dir + '**/*.txt', recursive=True):
print(filename)
Comme mentionné dans la documentation
Si récursif est vrai, le modèle '**' correspondra à tous les fichiers et à zéro ou plusieurs répertoires et sous-répertoires.
Si vous voulez tous les fichiers, vous pouvez utiliser
import glob
for filename in glob.iglob(root_dir + '**/*', recursive=True):
print(filename)
D'accord avec Dave Webb, os.walk
donnera un élément pour chaque répertoire de l'arborescence. Le fait est que vous n'avez simplement pas à vous soucier de subFolders
.
Un code comme celui-ci 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())
import glob
import os
root_dir = <root_dir_here>
for filename in glob.iglob(root_dir + '**/**', recursive=True):
if os.path.isfile(filename):
with open(filename,'r') as file:
print(file.read())
**/**
est utilisé pour obtenir tous les fichiers récursivement, y compris directory
.
if os.path.isfile(filename)
est utilisé pour vérifier si la variable filename
est file
ou directory
, si c'est un fichier, alors nous pouvons lire ce fichier. Ici, je suis en train d'imprimer un fichier.
utilisez os.path.join()
pour construire vos chemins.
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()
TL; DR: Ceci est l'équivalent de find -type f
pour parcourir tous les fichiers dans tous les répertoires ci-dessous, y compris celui en cours:
for currentpath, dirs, files in os.walk('.'):
for file in files:
print(os.path.join(currentpath, file))
Comme déjà mentionné dans d'autres réponses, os.walk()
est la réponse, mais elle pourrait être mieux expliquée. C'est assez simple! Marchons à travers cet arbre:
docs/
└── doc1.odt
pics/
todo.txt
Avec ce code:
for currentpath, folders, files in os.walk('.'):
print(currentpath)
Le currentpath
est le dossier actuel qu'il est en train de regarder. Cela produira:
.
./docs
./pics
Donc, il boucle trois fois, car il y a trois dossiers: le dossier en cours, docs
et pics
. Dans chaque boucle, il remplit les variables dirs
et files
avec tous les dossiers et fichiers. Montrons-leur:
for currentpath, folders, files in os.walk('.'):
print(currentpath, dirs, files)
Cela nous montre:
# currentpath folders files
. ['pics', 'docs'] ['todo.txt']
./pics [] []
./docs [] ['doc1.odt']
Ainsi, à la première ligne, nous voyons que nous sommes dans le dossier .
, qu'il contient deux dossiers, à savoir pics
et docs
, et qu'il existe un fichier, à savoir todo.txt
. . Vous n'avez rien à faire pour rentrer dans ces dossiers, car, comme vous le voyez, il est automatiquement récursif et ne vous donne que les fichiers des sous-dossiers. Et tous les sous-dossiers de celui-ci (bien que nous ne les ayons pas dans l'exemple).
Si vous voulez juste parcourir tous les fichiers, l'équivalent de find -type f
, vous pouvez faire ceci:
for currentpath, dirs, files in os.walk('.'):
for file in files:
print(os.path.join(currentpath, file))
Cela génère:
./todo.txt
./docs/doc1.odt
Essaye ça:
import os
import sys
for root, subdirs, files in os.walk(path):
for file in os.listdir(root):
filePath = os.path.join(root, file)
if os.path.isdir(filePath):
pass
else:
f = open (filePath, 'r')
# Do Stuff
Je pense que le problème est que vous ne traitez pas correctement la sortie de os.walk
.
Tout d'abord, changez:
filePath = rootdir + '/' + file
à:
filePath = root + '/' + file
rootdir
est votre répertoire de départ fixe; root
est un répertoire renvoyé par os.walk
.
Deuxièmement, vous n'avez pas besoin d'indenter votre boucle de traitement de fichier, car cela n'a aucun sens de l'exécuter pour chaque sous-répertoire. Vous aurez root
défini dans chaque sous-répertoire. Vous n'avez pas besoin de traiter les sous-répertoires à la main, sauf si vous souhaitez utiliser les répertoires eux-mêmes.
Si vous voulez une liste simple de tous les chemins sous un répertoire donné (comme find .
dans le shell):
files = [
os.path.join(parent, name)
for (parent, subdirs, files) in os.walk(YOUR_DIRECTORY)
for name in files + subdirs
]
Pour inclure uniquement les chemins d'accès complets aux fichiers sous le répertoire de base, laissez + subdirs
.
os.walk
fait la marche récursive par défaut. Pour chaque répertoire, en partant de la racine, le résultat est un triplet (répertoire, noms de répertoire, 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