Je travaille sur un script pour parcourir récursivement les sous-dossiers d'un dossier principal et créer une liste à partir d'un certain type de fichier. J'ai un problème avec le script. Son actuellement défini comme suit
for root, subFolder, files in os.walk(PATH):
for item in files:
if item.endswith(".txt") :
fileNamePath = str(os.path.join(root,subFolder,item))
le problème est que la variable de sous-dossier extrait une liste de sous-dossiers plutôt que le dossier dans lequel se trouve le fichier ITEM. Je pensais lancer une boucle for pour le sous-dossier avant et rejoindre la première partie du chemin, mais je pensais que je vérifiais si je vérifiais si quelqu'un avait des suggestions avant. Merci de votre aide!
Vous devriez utiliser le dirpath
que vous appelez root
. Les dirnames
sont fournis afin que vous puissiez le nettoyer s'il existe des dossiers dans lesquels vous ne souhaitez pas que os.walk
soit renvoyé.
import os
result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(PATH) for f in filenames if os.path.splitext(f)[1] == '.txt']
Edit:
Après le dernier vote négatif, il m'est apparu que glob
était un meilleur outil de sélection par extension.
import os
from glob import glob
result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))]
Aussi une version de générateur
from itertools import chain
result = (chain.from_iterable(glob(os.path.join(x[0], '*.txt')) for x in os.walk('.')))
Edit2 pour Python 3.4 +
from pathlib import Path
result = list(Path(".").rglob("*.[tT][xX][tT]"))
Modifié dans Python 3.5 : Prise en charge des globs récursifs à l’aide de "**".
glob.glob()
a un nouveau paramètre récursif .
Si vous voulez obtenir tous les fichiers .txt
sous my_path
(incluant récursivement des sous-répertoires):
import glob
files = glob.glob(my_path + '/**/*.txt', recursive=True)
# my_path/ the dir
# **/ every file and dir under my_path
# *.txt every file that ends with '.txt'
Si vous avez besoin d'un itérateur, vous pouvez utiliser iglob comme alternative:
for file in glob.iglob(my_path, recursive=False):
# ...
Je vais traduire compréhension de la liste de John La Rooy en imbriqué, au cas où quelqu'un aurait du mal à le comprendre.
result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))]
Devrait être équivalent à:
import glob
result = []
for x in os.walk(PATH):
for y in glob.glob(os.path.join(x[0], '*.txt')):
result.append(y)
Voici la documentation pour compréhension de la liste et les fonctions os.walk et glob.glob .
Ce n'est pas la réponse la plus pythonique, mais je vais la mettre ici pour le plaisir, car c'est une bonne leçon de récursion
def find_files( files, dirs=[], extensions=[]):
new_dirs = []
for d in dirs:
try:
new_dirs += [ os.path.join(d, f) for f in os.listdir(d) ]
except OSError:
if os.path.splitext(d)[1] in extensions:
files.append(d)
if new_dirs:
find_files(files, new_dirs, extensions )
else:
return
Sur ma machine, j'ai deux dossiers, root
et root2
mender@multivax ]ls -R root root2
root:
temp1 temp2
root/temp1:
temp1.1 temp1.2
root/temp1/temp1.1:
f1.mid
root/temp1/temp1.2:
f.mi f.mid
root/temp2:
tmp.mid
root2:
dummie.txt temp3
root2/temp3:
song.mid
Disons que je veux trouver tous les fichiers .txt
et tous les fichiers .mid
de l'un ou l'autre de ces répertoires, alors je peux simplement le faire.
files = []
find_files( files, dirs=['root','root2'], extensions=['.mid','.txt'] )
print(files)
#['root2/dummie.txt',
# 'root/temp2/tmp.mid',
# 'root2/temp3/song.mid',
# 'root/temp1/temp1.1/f1.mid',
# 'root/temp1/temp1.2/f.mid']
La nouvelle bibliothèque pathlib
simplifie cela en une ligne:
from pathlib import Path
result = list(Path(PATH).glob('**/*.txt'))
Vous pouvez également utiliser la version du générateur:
from pathlib import Path
for file in Path(PATH).glob('**/*.txt'):
pass
Cela retourne les objets Path
, que vous pouvez utiliser pour à peu près n'importe quoi, ou obtenir le nom du fichier sous forme de chaîne par file.name
.
Récursif est nouveau dans Python 3.5, il ne fonctionnera donc pas sur Python 2.7. Voici l'exemple qui utilise les chaînes r
, il vous suffit donc de fournir le chemin tel qu'il est sur Win, Lin, ...
import glob
mypath=r"C:\Users\dj\Desktop\nba"
files = glob.glob(mypath + r'\**\*.py', recursive=True)
# print(files) # as list
for f in files:
print(f) # Nice looking single line per file
Remarque: Il répertoriera tous les fichiers, quelle que soit leur profondeur.