Elenco di alberi di directory in Python


Risposte:


615

Questo è un modo per attraversare ogni file e directory in un albero di directory:

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
E se si esegue questo codice (così com'è) dalla shell Python, ricordare che Ctrl + C interromperà l'output a detta shell. ;)
gary,

41
Questo sarà ricorsivamente elenca file e directory
RDS

È anche possibile modificare l'elenco dei dirnames per evitare che ricorra in alcuni percorsi.
bugloaf,

8
@ Clément "Quando topdown è True, il chiamante può modificare sul posto l'elenco di dirnames (magari usando l'assegnazione del o slice), e walk () si ripeterà solo nelle sottodirectory i cui nomi rimangono nei dirnames; questo può essere usato per potare cercare, imporre un ordine specifico di visita o persino informare walk () sulle directory che il chiamante crea o rinomina prima di riprendere a camminare () di nuovo. " da docs.python.org/2/library/os.html#os.walk
bugloaf

Il modo più semplice di ignorare alcune directory è in primo luogo non aggiungerle ai dirnamesfor subdirname in dirnames: if subdirname != '.git'
smci

537

Puoi usare

os.listdir(path)

Per riferimento e altre funzioni del sistema operativo, guarda qui:


1
bene la domanda originale è abbastanza vaga da non sapere se volevano una soluzione ricorsiva. "tutti i file in una directory" potrebbero essere interpretati come ricorsivi.
Tommy,

3
@ Tommy, una "directory" è una struttura di dati chiaramente definita e si riferisce a "ls" piuttosto che a "ls -R". Inoltre, quasi tutti gli strumenti UNIX non funzionano in modo ricorsivo per impostazione predefinita. Non so cosa volesse dire l'interrogante, ma ciò che ha scritto era chiaro.
Torsten Bronger,

I documenti di Python 3 ti dicono di usare os.scandirinvece, poiché in molti casi ti consente di prevenire le chiamate di sistema, dando una velocità gratuita (sia IPC che IO sono lenti).
Jappie Kerk,

5
listdir ti dà l'unico nome di file nella directory, c'è un metodo disponibile per ottenere il percorso completo?
greperror,

1
@greperror È possibile utilizzare os.path.abspath per ottenere il percorso completo. Inoltre, per verificare se un determinato percorso è un file, utilizzare os.path.isfile o os.path.isdir.
Aleksandar,

111

Ecco una funzione di aiuto che uso abbastanza spesso:

import os

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

3
Un generatore sarebbe migliore.
Robert Siemer,

1
@RobertSiemer che dipende dall'uso. In molti casi, un elenco sarebbe meglio, ma immagino che un generatore sia più versatile poiché può essere convertito in un elenco. Dipende se stai cercando, versatilità o qualcosa di un po 'più snello.
James Mchugh,

3
Sono passati dieci anni, ma penso di averlo fatto in questo modo perché os.listdir () restituisce un elenco e lo stavo imitando.
Giltay,

82
import os

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

16
r'C:\temp'è più chiaro e preferito a "C:\\temp"Rawstrings sono preferibili alle barre rovesciate di fuga.
smci

13

Se hai bisogno di abilità da globbing, c'è anche un modulo per quello. Per esempio:

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

restituirà qualcosa come:

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

Vedi la documentazione qui .


10

Prova questo:

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

In una riga: [top + os.sep + f per top, dirs, file in os.walk ('./') per f nei file]
J. Peterson,

9

Per i file nella directory di lavoro corrente senza specificare un percorso

Python 2.7:

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

Python 3.x:

import os
os.listdir()

Grazie a Stam Kaly per il commento su Python 3.x


5
os.listdir()elenca gli elementi nella directory corrente per impostazione predefinita! Quindi non c'è bisogno di os.getcwd():)
Stam Kaly,

Come lo farei? Quando uso >>> os.listdir () senza un argomento ottengo: TypeError: listdir () accetta esattamente 1 argomento (0 dato)
Dave Engineer

2
Presumo tu stia funzionando su 2.7. Questo è stato aggiunto il 3.x
Stam Kaly

5

Un'implementazione ricorsiva

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

Ho scritto una versione lunga, con tutte le opzioni di cui potrei avere bisogno: http://sam.nipl.net/code/python/find.py

Immagino che andrà bene anche qui:

#!/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

Ecco un'altra opzione.

os.scandir(path='.')

Restituisce un iteratore di oggetti os.DirEntry corrispondenti alle voci (insieme alle informazioni sugli attributi del file) nella directory fornita dal percorso.

Esempio:

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

L'uso di scandir () anziché listdir () può aumentare significativamente le prestazioni del codice che necessita anche di informazioni sul tipo di file o sugli attributi di file , poiché gli oggetti os.DirEntry espongono queste informazioni se il sistema operativo le fornisce durante la scansione di una directory. Tutti i metodi os.DirEntry possono eseguire una chiamata di sistema, ma is_dir () e is_file () di solito richiedono solo una chiamata di sistema per collegamenti simbolici; os.DirEntry.stat () richiede sempre una chiamata di sistema su Unix ma ne richiede solo una per i collegamenti simbolici su Windows.

Python Docs


3

Mentre os.listdir()va bene per generare un elenco di nomi di file e dir, spesso vuoi fare di più una volta che hai quei nomi - e in Python3, pathlib rende semplici quelle altre faccende. Diamo un'occhiata e vediamo se ti piace tanto quanto me.

Per elencare i contenuti di dir, costruisci un oggetto Path e prendi l'iteratore:

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

Se vogliamo solo un elenco di nomi di cose:

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

Se vuoi solo i dir:

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

Se vuoi i nomi di tutti i file conf in quell'albero:

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

Se si desidera un elenco di file conf nella struttura> = 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',

Risolvere i percorsi relativi diventa facile:

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

Navigare con un percorso è abbastanza chiaro (anche se inaspettato):

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

Una bella riga per elencare solo i file in modo ricorsivo. L'ho usato nella mia direttiva package_data setup.py:

import os

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

So che non è la risposta alla domanda, ma può tornare utile


1

Per Python 2

#!/bin/python2

import os

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

Per Python 3

Per filtro e mappa, devi avvolgerli con list ()

#!/bin/python3

import os

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

La raccomandazione ora è di sostituire l'uso della mappa e del filtro con espressioni di generatori o comprensioni di elenchi:

#!/bin/python

import os

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

1

Ecco una versione Pythonic a una riga:

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)]

Questo codice elenca il percorso completo di tutti i file e directory nel nome di directory specificato.


Grazie Saleh, ma il tuo codice non ha funzionato completamente e quello funzionato è stato modificato come segue: 'dir =' nome_directory_name 'nomi file = [os.path.abspath (os.path.join (dir, i)) per i in os.listdir (dir)] '
HassanSh__3571619

1

So che questa è una vecchia domanda. Questo è un modo pulito in cui mi sono imbattuto se sei su una macchina 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
Questa domanda ha già una risposta perfettamente valida, non è necessario rispondere di nuovo
Mike Pennington,

0

Cordiali saluti Aggiunge un filtro di os di importazione di file di estensione o 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

Se immagino, lo aggiungerei. Un modo semplice e sporco per fare ricerche con caratteri jolly.

import re
import os

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

0

Il codice seguente elenca le directory e i file all'interno della directory

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

Quello che ha funzionato con me è una specie di versione modificata dalla risposta di Saleh sopra.

Il codice è il seguente:

"dir = 'nome_directory_nome' nomi file = [os.path.abspath (os.path.join (dir, i)) per i in os.listdir (dir)]"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.