Je sais que nous pouvons utiliser os.walk () pour lister tous les sous-répertoires ou tous les fichiers d’un répertoire. Cependant, j'aimerais lister le contenu complet de l'arborescence de répertoires:
Comment y parvenir au mieux en Python?
Voici une fonction pour le faire avec le formatage:
import os
def list_files(startpath):
for root, dirs, files in os.walk(startpath):
level = root.replace(startpath, '').count(os.sep)
indent = ' ' * 4 * (level)
print('{}{}/'.format(indent, os.path.basename(root)))
subindent = ' ' * 4 * (level + 1)
for f in files:
print('{}{}'.format(subindent, f))
Une solution sans votre indentation:
for path, dirs, files in os.walk(given_path):
print path
for f in files:
print f
os.walk fait déjà la promenade de haut en bas que vous recherchez en profondeur.
Ignorer la liste des répertoires empêche le chevauchement que vous mentionnez.
Je suis venu ici pour chercher la même chose et utilisé dhobbs answer pour moi. Pour remercier la communauté, j’ai ajouté quelques arguments pour écrire dans un fichier, comme le demandait akshay, et j’ai rendu l’affichage facultatif des fichiers afin qu’il ne s’agisse pas d’une sortie si binaire. En outre, l'indentation est devenue un argument facultatif afin que vous puissiez le modifier, car certains le préfèrent à 2 et d'autres à 4.
Utilisé différentes boucles afin que celui qui ne montre pas les fichiers ne vérifie pas si cela doit se faire à chaque itération.
J'espère que ça aide quelqu'un d'autre, car la réponse de dhobbs m'a aidé. Merci beaucoup.
def showFolderTree(path,show_files=False,indentation=2,file_output=False):
"""
Shows the content of a folder in a tree structure.
path -(string)- path of the root folder we want to show.
show_files -(boolean)- Whether or not we want to see files listed.
Defaults to False.
indentation -(int)- Indentation we want to use, defaults to 2.
file_output -(string)- Path (including the name) of the file where we want
to save the tree.
"""
tree = []
if not show_files:
for root, dirs, files in os.walk(path):
level = root.replace(path, '').count(os.sep)
indent = ' '*indentation*(level)
tree.append('{}{}/'.format(indent,os.path.basename(root)))
if show_files:
for root, dirs, files in os.walk(path):
level = root.replace(path, '').count(os.sep)
indent = ' '*indentation*(level)
tree.append('{}{}/'.format(indent,os.path.basename(root)))
for f in files:
subindent=' ' * indentation * (level+1)
tree.append('{}{}'.format(subindent,f))
if file_output:
output_file = open(file_output,'w')
for line in tree:
output_file.write(line)
output_file.write('\n')
else:
# Default behaviour: print on screen.
for line in tree:
print line
Basé sur ce post fantastique
http://code.activestate.com/recipes/217212-treepy-graphically-displays-the-directory-structur/
Voici un raffinement à se comporter exactement comme
http://linux.die.net/man/1/tree
#!/usr/bin/env python2 # - * - codage: utf-8 - * - # tree.py # # # Écrit par Doug Dahms # # Imprime l’arborescence correspondant au chemin indiqué sur la ligne de commande À partir de os import listdir, sep .__ à partir de os.path import abspath, nom de base, isdir .____ argv def tree (rép, padding, print_files = False, isLast = False, isFirst = False): si isFirst: print padding.decode ('utf8') [: - 1] .encode ('utf8') + dir autre: si isLast: print padding.decode ('utf8') [: - 1] .encode ('utf8') + '└──' + nom de base (abspath (dir)) autre: print padding.decode ('utf8') [: - 1] .encode ('utf8') + '├──' + nom de base (abspath (dir)) fichiers = [] si print_files: fichiers = listdir (dir) autre: files = [x pour x dans listdir (dir) si isdir (dir + sep + x)] sinon isFirst: padding = padding + '' fichiers = triés (fichiers, clé = lambda s: s.lower ()) compte = 0 last = len (file) - 1 pour i, fichier en énumérer (fichiers): compte + = 1 chemin = dir + sep + fichier isLast = i == dernier si isdir (chemin): si compte == len (fichiers): si isFirst: tree (chemin d'accès, padding, print_files, isLast, False) autre: tree (chemin d'accès, padding + '', print_files, isLast, False) autre: tree (chemin d'accès, padding + '│', fichiers_impression, isLast, False) autre: si isLast: print padding + '└──' + file autre: print padding + '├──' + file def usage (): return '' 'Utilisation:% s [-f] Arborescence d'impression du chemin spécifié Options: - f Imprime les fichiers ainsi que les répertoires PATH Chemin d'accès au processus' ''% basename (argv [0]) def main (): si len (argv) == 1: utilisation de l'impression () Elif len (argv) == 2: # imprimer seulement les annuaires chemin = argv [1] si isdir (chemin): arbre (chemin, '', False, False, True) autre: print 'ERROR: \' '+ path +'\'n'est pas un répertoire' Elif len (argv) == 3 et argv [1] == '-f': # imprimer des répertoires et des fichiers chemin = argv [2] si isdir (chemin): arbre (chemin, '', vrai, faux, vrai) autre: print 'ERROR: \' '+ path +'\'n'est pas un répertoire' autre: print usage () if __== '__main __': principale()
import os
def fs_tree_to_dict(path_):
file_token = ''
for root, dirs, files in os.walk(path_):
tree = {d: fs_tree_to_dict(os.path.join(root, d)) for d in dirs}
tree.update({f: file_token for f in files})
return tree # note we discontinue iteration trough os.walk
Si quelqu'un est intéressé, cette fonction récursive renvoie la structure imbriquée de dictionnaires. Les clés sont des noms file system
(de répertoires et de fichiers), les valeurs sont les suivantes:
file_token
)Les chaînes désignant les fichiers sont vides dans cet exemple. Ils peuvent aussi être par exemple contenu du fichier donné ou les informations de son propriétaire ou des privilèges ou tout autre objet qu'un dict. À moins qu'il s'agisse d'un dictionnaire, il peut être facilement distingué d'un "type de répertoire" lors d'opérations ultérieures.
Avoir un tel arbre dans un système de fichiers:
# bash:
$ tree /tmp/ex
/tmp/ex
├── d_a
│ ├── d_a_a
│ ├── d_a_b
│ │ └── f1.txt
│ ├── d_a_c
│ └── fa.txt
├── d_b
│ ├── fb1.txt
│ └── fb2.txt
└── d_c
Le résultat sera:
# python 2 or 3:
>>> fs_tree_to_dict("/tmp/ex")
{
'd_a': {
'd_a_a': {},
'd_a_b': {
'f1.txt': ''
},
'd_a_c': {},
'fa.txt': ''
},
'd_b': {
'fb1.txt': '',
'fb2.txt': ''
},
'd_c': {}
}
Si vous aimez ça, j'ai déjà créé un paquet (Python 2 & 3) avec ce genre de choses (et un assistant Nice pyfakefs
): https://pypi.org/project/fsforge/
Semblable aux réponses ci-dessus, mais pour python3, sans doute lisible et extensible:
from pathlib import Path
class DisplayablePath(object):
display_filename_prefix_middle = '├──'
display_filename_prefix_last = '└──'
display_parent_prefix_middle = ' '
display_parent_prefix_last = '│ '
def __init__(self, path, parent_path, is_last):
self.path = Path(str(path))
self.parent = parent_path
self.is_last = is_last
if self.parent:
self.depth = self.parent.depth + 1
else:
self.depth = 0
@property
def displayname(self):
if self.path.is_dir():
return self.path.name + '/'
return self.path.name
@classmethod
def make_tree(cls, root, parent=None, is_last=False, criteria=None):
root = Path(str(root))
criteria = criteria or cls._default_criteria
displayable_root = cls(root, parent, is_last)
yield displayable_root
children = sorted(list(path
for path in root.iterdir()
if criteria(path)),
key=lambda s: str(s).lower())
count = 1
for path in children:
is_last = count == len(children)
if path.is_dir():
yield from cls.make_tree(path,
parent=displayable_root,
is_last=is_last,
criteria=criteria)
else:
yield cls(path, displayable_root, is_last)
count += 1
@classmethod
def _default_criteria(cls, path):
return True
@property
def displayname(self):
if self.path.is_dir():
return self.path.name + '/'
return self.path.name
def displayable(self):
if self.parent is None:
return self.displayname
_filename_prefix = (self.display_filename_prefix_last
if self.is_last
else self.display_filename_prefix_middle)
parts = ['{!s} {!s}'.format(_filename_prefix,
self.displayname)]
parent = self.parent
while parent and parent.parent is not None:
parts.append(self.display_parent_prefix_middle
if parent.is_last
else self.display_parent_prefix_last)
parent = parent.parent
return ''.join(reversed(parts))
Exemple d'utilisation:
paths = DisplayablePath.make_tree(Path('doc'))
for path in paths:
print(path.displayable())
Exemple de sortie:
doc/
├── _static/
│ ├── embedded/
│ │ ├── deep_file
│ │ └── very/
│ │ └── deep/
│ │ └── folder/
│ │ └── very_deep_file
│ └── less_deep_file
├── about.rst
├── conf.py
└── index.rst
Vous pouvez exécuter la commande 'tree' de Linux Shell.
Installation:
~$Sudo apt install tree
Utilisation en python
>>> import os
>>> os.system('tree <desired path>')
Exemple:
>>> os.system('tree ~/Desktop/myproject')
Cela vous donne une structure plus propre et est visuellement plus complet et facile à taper.
En plus de la réponse dhobbs ci-dessus ( https://stackoverflow.com/a/9728478/624597 ), voici une fonctionnalité supplémentaire permettant de stocker les résultats dans un fichier (je l'utilise personnellement pour copier et coller dans FreeMind pour avoir une bonne vue d'ensemble de la structure, j'ai donc utilisé des tabulations au lieu d'espaces pour l'indentation):
import os
def list_files(startpath):
with open("folder_structure.txt", "w") as f_output:
for root, dirs, files in os.walk(startpath):
level = root.replace(startpath, '').count(os.sep)
indent = '\t' * 1 * (level)
output_string = '{}{}/'.format(indent, os.path.basename(root))
print(output_string)
f_output.write(output_string + '\n')
subindent = '\t' * 1 * (level + 1)
for f in files:
output_string = '{}{}'.format(subindent, f)
print(output_string)
f_output.write(output_string + '\n')
list_files(".")
Peut-être plus rapide que @ellockie (peut-être)
import os def file_writer (text): avec open ("folder_structure.txt", "a") en tant que f_output: f_output.write (text) def list_files (chemin d'accès): pour root, dirs, fichiers dans os.walk (startpath): level = root.replace (startpath, '') .count (os.sep) indent = '\ t' * 1 * (niveau) output_string = '{} {}/\ n'.format (indent, os.path.basename (root)) file_writer (chaîne_sortie) sous-indice = '\ t' * 1 * (niveau + 1) chaîne_sortie = '% s% s\n'% (sous-indent, [f pour f dans les fichiers]) file_writer (''. join (output_string)) list_files ("/")
Résultats du test en capture d'écran ci-dessous:
Ici vous pouvez trouver le code avec une sortie comme ceci: https://stackoverflow.com/a/56622847/66713
V .
|-> V folder1
| |-> V folder2
| | |-> V folder3
| | | |-> file3.txt
| | |-> file2.txt
| |-> V folderX
| |-> file1.txt
|-> 02-hw1_wdwwfm.py
|-> 06-t1-home1.py
|-> 06-t1-home2.py
|-> hw1.py
Cette solution ne fonctionnera que si vous avez installé tree
sur votre système. Cependant, je laisse cette solution ici au cas où cela aiderait quelqu'un d'autre.
Vous pouvez indiquer à l’arbre de sortir l’arborescence au format XML (tree -X
) ou JSON (tree -J
). JSON peut bien sûr être analysé directement avec python et XML peut facilement être lu avec lxml
.
Avec la structure de répertoire suivante comme exemple:
[sri@localhost Projects]$ tree --charset=ascii bands
bands
|-- DreamTroll
| |-- MattBaldwinson
| |-- members.txt
| |-- PaulCarter
| |-- SimonBlakelock
| `-- Rob Stringer
|-- KingsX
| |-- DougPinnick
| |-- JerryGaskill
| |-- members.txt
| `-- TyTabor
|-- Megadeth
| |-- DaveMustaine
| |-- DavidEllefson
| |-- DirkVerbeuren
| |-- KikoLoureiro
| `-- members.txt
|-- Nightwish
| |-- EmppuVuorinen
| |-- FloorJansen
| |-- JukkaNevalainen
| |-- MarcoHietala
| |-- members.txt
| |-- TroyDonockley
| `-- TuomasHolopainen
`-- Rush
|-- AlexLifeson
|-- GeddyLee
`-- NeilPeart
5 directories, 25 files
XML
<?xml version="1.0" encoding="UTF-8"?>
<tree>
<directory name="bands">
<directory name="DreamTroll">
<file name="MattBaldwinson"></file>
<file name="members.txt"></file>
<file name="PaulCarter"></file>
<file name="RobStringer"></file>
<file name="SimonBlakelock"></file>
</directory>
<directory name="KingsX">
<file name="DougPinnick"></file>
<file name="JerryGaskill"></file>
<file name="members.txt"></file>
<file name="TyTabor"></file>
</directory>
<directory name="Megadeth">
<file name="DaveMustaine"></file>
<file name="DavidEllefson"></file>
<file name="DirkVerbeuren"></file>
<file name="KikoLoureiro"></file>
<file name="members.txt"></file>
</directory>
<directory name="Nightwish">
<file name="EmppuVuorinen"></file>
<file name="FloorJansen"></file>
<file name="JukkaNevalainen"></file>
<file name="MarcoHietala"></file>
<file name="members.txt"></file>
<file name="TroyDonockley"></file>
<file name="TuomasHolopainen"></file>
</directory>
<directory name="Rush">
<file name="AlexLifeson"></file>
<file name="GeddyLee"></file>
<file name="NeilPeart"></file>
</directory>
</directory>
<report>
<directories>5</directories>
<files>25</files>
</report>
</tree>
JSON
[sri@localhost Projects]$ tree -J bands
[
{"type":"directory","name":"bands","contents":[
{"type":"directory","name":"DreamTroll","contents":[
{"type":"file","name":"MattBaldwinson"},
{"type":"file","name":"members.txt"},
{"type":"file","name":"PaulCarter"},
{"type":"file","name":"RobStringer"},
{"type":"file","name":"SimonBlakelock"}
]},
{"type":"directory","name":"KingsX","contents":[
{"type":"file","name":"DougPinnick"},
{"type":"file","name":"JerryGaskill"},
{"type":"file","name":"members.txt"},
{"type":"file","name":"TyTabor"}
]},
{"type":"directory","name":"Megadeth","contents":[
{"type":"file","name":"DaveMustaine"},
{"type":"file","name":"DavidEllefson"},
{"type":"file","name":"DirkVerbeuren"},
{"type":"file","name":"KikoLoureiro"},
{"type":"file","name":"members.txt"}
]},
{"type":"directory","name":"Nightwish","contents":[
{"type":"file","name":"EmppuVuorinen"},
{"type":"file","name":"FloorJansen"},
{"type":"file","name":"JukkaNevalainen"},
{"type":"file","name":"MarcoHietala"},
{"type":"file","name":"members.txt"},
{"type":"file","name":"TroyDonockley"},
{"type":"file","name":"TuomasHolopainen"}
]},
{"type":"directory","name":"Rush","contents":[
{"type":"file","name":"AlexLifeson"},
{"type":"file","name":"GeddyLee"},
{"type":"file","name":"NeilPeart"}
]}
]},
{"type":"report","directories":5,"files":25}
]
Pour ceux qui cherchent encore une réponse. Voici une approche récursive pour obtenir les chemins dans un dictionnaire.
import os
def list_files(startpath):
for root, dirs, files in os.walk(startpath):
dir_content = []
for dir in dirs:
go_inside = os.path.join(startpath, dir)
dir_content.append(list_files(go_inside))
files_lst = []
for f in files:
files_lst.append(f)
return {'name': root, 'files': files_lst, 'dirs': dir_content}