Liste de l'arborescence des répertoires en Python


Réponses:


615

C'est un moyen de parcourir chaque fichier et répertoire dans une arborescence de répertoires:

import os

for dirname, dirnames, filenames in os.walk('.'):
    # print path to all subdirectories first.
    for subdirname in dirnames:
        print(os.path.join(dirname, subdirname))

    # print path to all filenames.
    for filename in filenames:
        print(os.path.join(dirname, filename))

    # Advanced usage:
    # editing the 'dirnames' list will stop os.walk() from recursing into there.
    if '.git' in dirnames:
        # don't go into any .git directories.
        dirnames.remove('.git')

19
Et si vous exécutez ce code (tel quel) à partir du shell Python, rappelez-vous que Ctrl + C arrêtera la sortie vers ledit shell. ;)
gary

41
Ceci
listera

Vous pouvez même modifier la liste des noms de répertoires pour l'empêcher de se reproduire sur certains chemins.
bugloaf

8
@ Clément "Lorsque topdown est True, l'appelant peut modifier la liste des noms de répertoires sur place (peut-être en utilisant l'affectation del ou slice), et walk () ne récursera que dans les sous-répertoires dont les noms restent dans les noms de répertoires; cela peut être utilisé pour élaguer le rechercher, imposer un ordre de visite spécifique ou même informer walk () des répertoires que l'appelant crée ou renomme avant de reprendre walk (). " de docs.python.org/2/library/os.html#os.walk
bugloaf

La manière la plus simple d'ignorer certains répertoires est de ne pas les ajouter aux répertoires en premier lieufor subdirname in dirnames: if subdirname != '.git'
smci

537

Vous pouvez utiliser

os.listdir(path)

Pour référence et plus de fonctions os, regardez ici:


1
eh bien la question d'origine est juste assez vague pour ne pas savoir s'ils voulaient une solution récursive. "tous les fichiers d'un répertoire" peuvent être interprétés comme récursifs.
Tommy

3
@Tommy, un «répertoire» est une structure de données clairement définie, et il fait référence à «ls» plutôt qu'à «ls -R». De plus, presque tous les outils UNIX ne fonctionnent pas récursivement par défaut. Je ne sais pas ce que le questionneur voulait dire, mais ce qu'il a écrit était clair.
Torsten Bronger

Les documents de python 3 vous disent os.scandircependant d'utiliser à la place, car dans de nombreux cas, cela vous permet d'empêcher les appels système, ce qui donne une accélération gratuite (IPC et IO sont lents).
Jappie Kerk

5
listdir vous donne le seul nom de fichier dans le répertoire, y a-t-il une méthode disponible pour obtenir le chemin complet?
greperror

1
@greperror Vous pouvez utiliser os.path.abspath pour obtenir le chemin complet. De plus, pour vérifier si un chemin donné est un fichier, utilisez os.path.isfile ou os.path.isdir.
Aleksandar

112

Voici une fonction d'aide que j'utilise assez souvent:

import os

def listdir_fullpath(d):
    return [os.path.join(d, f) for f in os.listdir(d)]

3
Un générateur serait mieux.
Robert Siemer

1
@RobertSiemer qui dépend de l'utilisation. Dans de nombreux cas, une liste serait mieux, mais je suppose qu'un générateur est plus polyvalent car il peut être converti en liste. Cela dépend si vous recherchez, la polyvalence ou quelque chose d'un peu plus rationalisé.
James Mchugh

4
Cela fait dix ans, mais je pense que je l'ai fait de cette façon parce que os.listdir () renvoie une liste et j'imitais cela.
giltay

82
import os

for filename in os.listdir("C:\\temp"):
    print  filename

16
r'C:\temp'est plus clair et préféré à "C:\\temp"Rawstrings sont préférables aux barres obliques inverses.
smci

13

Si vous avez besoin de capacités globbing, il existe également un module pour cela. Par exemple:

import glob
glob.glob('./[0-9].*')

renverra quelque chose comme:

['./1.gif', './2.txt']

Voir la documentation ici .


10

Essaye ça:

import os
for top, dirs, files in os.walk('./'):
    for nm in files:       
        print os.path.join(top, nm)

En une ligne: [top + os.sep + f pour top, dirs, fichiers dans os.walk ('./') pour f dans les fichiers]
J. Peterson

9

Pour les fichiers dans le répertoire de travail actuel sans spécifier de chemin

Python 2.7:

import os
os.listdir(os.getcwd())

Python 3.x:

import os
os.listdir()

Merci à Stam Kaly pour ses commentaires sur python 3.x


5
os.listdir()liste les éléments du répertoire courant par défaut! Donc pas besoin de os.getcwd():)
Stam Kaly

Comment pourrais-je faire ça? Lorsque j'utilise >>> os.listdir () sans argument, j'obtiens: TypeError: listdir () prend exactement 1 argument (0 donné)
Dave Engineer

2
Je suppose que vous utilisez 2.7. Ceci a été ajouté le 3.x
Stam Kaly

5

Une implémentation récursive

import os

def scan_dir(dir):
    for name in os.listdir(dir):
        path = os.path.join(dir, name)
        if os.path.isfile(path):
            print path
        else:
            scan_dir(path)

3

J'ai écrit une version longue, avec toutes les options dont j'ai besoin: http://sam.nipl.net/code/python/find.py

Je suppose que ça ira ici aussi:

#!/usr/bin/env python

import os
import sys

def ls(dir, hidden=False, relative=True):
    nodes = []
    for nm in os.listdir(dir):
        if not hidden and nm.startswith('.'):
            continue
        if not relative:
            nm = os.path.join(dir, nm)
        nodes.append(nm)
    nodes.sort()
    return nodes

def find(root, files=True, dirs=False, hidden=False, relative=True, topdown=True):
    root = os.path.join(root, '')  # add slash if not there
    for parent, ldirs, lfiles in os.walk(root, topdown=topdown):
        if relative:
            parent = parent[len(root):]
        if dirs and parent:
            yield os.path.join(parent, '')
        if not hidden:
            lfiles   = [nm for nm in lfiles if not nm.startswith('.')]
            ldirs[:] = [nm for nm in ldirs  if not nm.startswith('.')]  # in place
        if files:
            lfiles.sort()
            for nm in lfiles:
                nm = os.path.join(parent, nm)
                yield nm

def test(root):
    print "* directory listing, with hidden files:"
    print ls(root, hidden=True)
    print
    print "* recursive listing, with dirs, but no hidden files:"
    for f in find(root, dirs=True):
        print f
    print

if __name__ == "__main__":
    test(*sys.argv[1:])

3

Voici une autre option.

os.scandir(path='.')

Il renvoie un itérateur d'objets os.DirEntry correspondant aux entrées (ainsi que les informations d'attribut de fichier) dans le répertoire donné par path.

Exemple:

with os.scandir(path) as it:
    for entry in it:
        if not entry.name.startswith('.'):
            print(entry.name)

L'utilisation de scandir () au lieu de listdir () peut augmenter considérablement les performances du code qui nécessite également des informations sur le type ou l'attribut de fichier , car les objets os.DirEntry exposent ces informations si le système d'exploitation les fournit lors de l'analyse d'un répertoire. Toutes les méthodes os.DirEntry peuvent effectuer un appel système, mais is_dir () et is_file () nécessitent généralement un appel système uniquement pour les liens symboliques; os.DirEntry.stat () nécessite toujours un appel système sous Unix mais n'en requiert qu'un pour les liens symboliques sous Windows.

Documents Python


3

Bien que ce os.listdir()soit bien pour générer une liste de noms de fichiers et de répertoires, vous voulez souvent en faire plus une fois que vous avez ces noms - et en Python3, pathlib simplifie ces autres tâches. Jetons un coup d'œil et voyons si vous l'aimez autant que moi.

Pour lister le contenu du répertoire, construisez un objet Path et récupérez l'itérateur:

In [16]: Path('/etc').iterdir()
Out[16]: <generator object Path.iterdir at 0x110853fc0>

Si nous voulons juste une liste de noms de choses:

In [17]: [x.name for x in Path('/etc').iterdir()]
Out[17]:
['emond.d',
 'ntp-restrict.conf',
 'periodic',

Si vous voulez juste les dirs:

In [18]: [x.name for x in Path('/etc').iterdir() if x.is_dir()]
Out[18]:
['emond.d',
 'periodic',
 'mach_init.d',

Si vous voulez les noms de tous les fichiers conf dans cette arborescence:

In [20]: [x.name for x in Path('/etc').glob('**/*.conf')]
Out[20]:
['ntp-restrict.conf',
 'dnsextd.conf',
 'syslog.conf',

Si vous voulez une liste de fichiers conf dans l'arborescence> = 1K:

In [23]: [x.name for x in Path('/etc').glob('**/*.conf') if x.stat().st_size > 1024]
Out[23]:
['dnsextd.conf',
 'pf.conf',
 'autofs.conf',

La résolution des chemins relatifs devient facile:

In [32]: Path('../Operational Metrics.md').resolve()
Out[32]: PosixPath('/Users/starver/code/xxxx/Operational Metrics.md')

Naviguer avec un chemin est assez clair (bien qu'inattendu):

In [10]: p = Path('.')

In [11]: core = p / 'web' / 'core'

In [13]: [x for x in core.iterdir() if x.is_file()]
Out[13]:
[PosixPath('web/core/metrics.py'),
 PosixPath('web/core/services.py'),
 PosixPath('web/core/querysets.py'),

1

Une belle doublure pour ne lister que les fichiers récursivement. J'ai utilisé ceci dans ma directive package_data setup.py:

import os

[os.path.join(x[0],y) for x in os.walk('<some_directory>') for y in x[2]]

Je sais que ce n'est pas la réponse à la question, mais peut être utile


1

Pour Python 2

#!/bin/python2

import os

def scan_dir(path):
    print map(os.path.abspath, os.listdir(pwd))

Pour Python 3

Pour le filtre et la carte, vous devez les envelopper avec list ()

#!/bin/python3

import os

def scan_dir(path):
    print(list(map(os.path.abspath, os.listdir(pwd))))

La recommandation est maintenant de remplacer votre utilisation de la carte et du filtre par des expressions de générateurs ou des compréhensions de liste:

#!/bin/python

import os

def scan_dir(path):
    print([os.path.abspath(f) for f in os.listdir(path)])

1

Voici une version Pythonic d'une ligne:

import os
dir = 'given_directory_name'
filenames = [os.path.join(os.path.dirname(os.path.abspath(__file__)),dir,i) for i in os.listdir(dir)]

Ce code répertorie le chemin d'accès complet de tous les fichiers et répertoires dans le nom de répertoire donné.


Merci Saleh, mais votre code n'a pas fonctionné complètement, et celui qui a fonctionné a été modifié comme suit: 'dir =' given_directory_name 'filenames = [os.path.abspath (os.path.join (dir, i)) for i in os.listdir (dir)] '
HassanSh__3571619

1

Je sais que c'est une vieille question. C'est une bonne façon de voir si vous êtes sur une machine liunx.

import subprocess
print(subprocess.check_output(["ls", "/"]).decode("utf8"))

0
#import modules
import os

_CURRENT_DIR = '.'


def rec_tree_traverse(curr_dir, indent):
    "recurcive function to traverse the directory"
    #print "[traverse_tree]"

    try :
        dfList = [os.path.join(curr_dir, f_or_d) for f_or_d in os.listdir(curr_dir)]
    except:
        print "wrong path name/directory name"
        return

    for file_or_dir in dfList:

        if os.path.isdir(file_or_dir):
            #print "dir  : ",
            print indent, file_or_dir,"\\"
            rec_tree_traverse(file_or_dir, indent*2)

        if os.path.isfile(file_or_dir):
            #print "file : ",
            print indent, file_or_dir

    #end if for loop
#end of traverse_tree()

def main():

    base_dir = _CURRENT_DIR

    rec_tree_traverse(base_dir," ")

    raw_input("enter any key to exit....")
#end of main()


if __name__ == '__main__':
    main()

5
Cette question a déjà une réponse parfaitement bonne, il n'est pas nécessaire d'y répondre à nouveau
Mike Pennington

0

FYI Ajouter un filtre d'os d'importation d'extensions ou de fichiers ext

path = '.'
for dirname, dirnames, filenames in os.walk(path):
    # print path to all filenames with extension py.
    for filename in filenames:
        fname_path = os.path.join(dirname, filename)
        fext = os.path.splitext(fname_path)[1]
        if fext == '.py':
            print fname_path
        else:
            continue

0

Si figuré, je jetterais cela. Un moyen simple et sale de faire des recherches génériques.

import re
import os

[a for a in os.listdir(".") if re.search("^.*\.py$",a)]

0

Le code ci-dessous répertorie les répertoires et les fichiers dans le répertoire

def print_directory_contents(sPath):
        import os                                       
        for sChild in os.listdir(sPath):                
            sChildPath = os.path.join(sPath,sChild)
            if os.path.isdir(sChildPath):
                print_directory_contents(sChildPath)
            else:
                print(sChildPath)

0

Celui qui a travaillé avec moi est une sorte de version modifiée de la réponse Saleh ci-dessus.

Le code est comme suit:

"dir = 'given_directory_name' filenames = [os.path.abspath (os.path.join (dir, i)) pour i dans os.listdir (dir)]"

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.