Listagem de árvore de diretório em Python

Respostas:

615

Esta é uma maneira de percorrer todos os arquivos e diretórios em uma árvore de diretórios:

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')
Jerub
fonte
19
E se você executar esse código (como está) no Python Shell, lembre-se de que Ctrl + C interromperá a saída para o referido shell. ;)
Gary
41
Isso listará recursivamente arquivos e diretórios
rds
Você pode até editar a lista de nomes de diretório para impedir que ela se repita em alguns caminhos.
bugloaf
8
@ Clément "Quando o topdown é True, o chamador pode modificar a lista de nomes de diretórios no local (talvez usando a atribuição del ou slice), e walk () recursará apenas nos subdiretórios cujos nomes permanecem em nomes de diretórios; isso pode ser usado para remover a pesquisar, impor uma ordem específica de visita ou até mesmo informar walk () sobre os diretórios que o chamador cria ou renomeia antes de retomar walk () novamente. " do docs.python.org/2/library/os.html#os.walk
bugloaf
A maneira mais simples de ignorar alguns diretórios é não adicioná-los à dirnames em primeiro lugarfor subdirname in dirnames: if subdirname != '.git'
SMCI
537

Você pode usar

os.listdir(path)

Para referência e mais funções, veja aqui:

rslite
fonte
1
bem, a pergunta original é vaga o suficiente para não saber se eles queriam uma solução recursiva. "todos os arquivos em um diretório" podem ser interpretados como recursivos.
Tommy
3
@ Tommy, um “diretório” é uma estrutura de dados claramente definida e refere-se a "ls" em vez de "ls -R". Além disso, quase todas as ferramentas UNIX não funcionam recursivamente por padrão. Não sei o que o interlocutor quis dizer, mas o que ele escreveu foi claro.
Torsten Bronger
No os.scandirentanto, os documentos do python 3 dizem para você usar , pois, em muitos casos, permite impedir chamadas do sistema, acelerando gratuitamente (o IPC e o IO são lentos).
precisa saber é o seguinte
5
listdir fornece o único nome do arquivo no diretório. Existe um método disponível para obter o caminho completo?
Greperror #
1
@greperror Você pode usar os.path.abspath para obter o caminho completo. Além disso, para verificar se um determinado caminho é um arquivo, use o arquivo os.path.isfile ou os.path.isdir.
28418 Aleksandar
111

Aqui está uma função auxiliar que eu uso com frequência:

import os

def listdir_fullpath(d):
    return [os.path.join(d, f) for f in os.listdir(d)]
giltay
fonte
3
Um gerador seria melhor.
Robert Siemer
1
@RobertSiemer que depende do uso. Em muitos casos, uma lista seria melhor, mas acho que um gerador é mais versátil, pois pode ser convertido em uma lista. Depende se você está procurando, versatilidade ou algo um pouco mais simplificado.
James Mchugh 9/08/19
3
Faz dez anos, mas acho que fiz dessa maneira porque os.listdir () retorna uma lista e eu estava imitando isso.
precisa saber é
82
import os

for filename in os.listdir("C:\\temp"):
    print  filename
curtisk
fonte
16
r'C:\temp'é mais claro e preferível a "C:\\temp"Rawstrings é preferível a evitar barras invertidas.
SMCI
13

Se você precisar de habilidades de globbing, há um módulo para isso também. Por exemplo:

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

retornará algo como:

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

Veja a documentação aqui .

kenny
fonte
10

Tente o seguinte:

import os
for top, dirs, files in os.walk('./'):
    for nm in files:       
        print os.path.join(top, nm)
paxdiablo
fonte
Em uma linha: [topo os.sep + + f para parte superior, dirs, ficheiros em os.walk ( './') para f em arquivos]
J. Peterson
9

Para arquivos no diretório de trabalho atual sem especificar um caminho

Python 2.7:

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

Python 3.x:

import os
os.listdir()

Obrigado a Stam Kaly por comentar sobre o python 3.x

Dave Engineer
fonte
5
os.listdir()lista elementos no diretório atual por padrão! Portanto, não há necessidade de os.getcwd():)
Stam Kaly
Como eu faria isso? Quando eu uso >>> os.listdir () sem um argumento que eu recebo: TypeError: listDir () recebe exatamente 1 argumento (0 dado)
Dave Engenheiro
2
Presumo que você esteja executando o 2.7. Isso foi adicionado na versão 3.x
Stam Kaly
5

Uma implementação recursiva

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)
Arnaldo P. Figueira Figueira
fonte
3

Eu escrevi uma versão longa, com todas as opções que preciso: http://sam.nipl.net/code/python/find.py

Eu acho que vai caber aqui também:

#!/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:])
Sam Watkins
fonte
3

Aqui está outra opção.

os.scandir(path='.')

Ele retorna um iterador dos objetos os.DirEntry correspondentes às entradas (junto com as informações do atributo do arquivo) no diretório fornecido pelo caminho.

Exemplo:

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

O uso de scandir () em vez de listdir () pode aumentar significativamente o desempenho do código que também precisa de informações sobre o tipo ou o atributo do arquivo , porque os objetos os.DirEntry expõem essas informações se o sistema operacional fornecer essas informações ao varrer um diretório. Todos os métodos os.DirEntry podem executar uma chamada do sistema, mas is_dir () e is_file () geralmente requerem apenas uma chamada do sistema para links simbólicos; os.DirEntry.stat () sempre requer uma chamada do sistema no Unix, mas apenas uma para links simbólicos no Windows.

Documentos do Python

Khaino
fonte
3

Embora os.listdir()seja bom para gerar uma lista de nomes de arquivos e diretórios, frequentemente você deseja fazer mais quando tiver esses nomes - e no Python3, o pathlib simplifica essas tarefas. Vamos dar uma olhada e ver se você gosta tanto quanto eu.

Para listar o conteúdo do diretório, construa um objeto Path e pegue o iterador:

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

Se queremos apenas uma lista de nomes de coisas:

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

Se você quiser apenas os diretórios:

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

Se você deseja os nomes de todos os arquivos conf nessa árvore:

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

Se você deseja uma lista de arquivos conf na árvore> = 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',

Resolver caminhos relativos fica fácil:

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

Navegar com um caminho é bastante claro (embora inesperado):

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'),
Steve Tarver
fonte
1

Um bom liner para listar apenas os arquivos recursivamente. Eu usei isso na minha diretiva setup.py package_data:

import os

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

Sei que não é a resposta para a pergunta, mas pode ser útil

fivetentaylor
fonte
1

Para Python 2

#!/bin/python2

import os

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

Para Python 3

Para filtro e mapa, você precisa envolvê-los com list ()

#!/bin/python3

import os

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

A recomendação agora é substituir o uso de mapa e filtro por expressões de geradores ou compreensão de lista:

#!/bin/python

import os

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

Aqui está uma versão Pythonic de uma linha:

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

Este código lista o caminho completo de todos os arquivos e diretórios no nome do diretório fornecido.

salehinejad
fonte
Obrigado Saleh, mas o seu código não funcionou completamente e o código funcionado foi modificado da seguinte forma: 'dir =' nome_do_diretório_nome 'nome dos arquivos = [os.path.abspath (os.path.join (dir, i)) para i em os.listdir (dir)] '
HassanSh__3571619
1

Eu sei que esta é uma pergunta antiga. Esta é uma maneira elegante de me deparar se você estiver em uma máquina liunx.

import subprocess
print(subprocess.check_output(["ls", "/"]).decode("utf8"))
apeter
fonte
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()
Alok
fonte
5
Esta questão já tem uma resposta perfeitamente boa, não há necessidade de responder novamente #
Mike Pennington
0

FYI Adicione um filtro de extensão ou importação de arquivo 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
moylop260
fonte
0

Se fosse o caso, eu jogaria isso para dentro. Maneira simples e suja de fazer pesquisas de caracteres curinga.

import re
import os

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

O código abaixo lista os diretórios e os arquivos no diretório

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)
Heenashree Khandelwal
fonte
0

O que trabalhou comigo é uma espécie de versão modificada da resposta de Saleh acima.

O código é o seguinte:

"dir = nomes de arquivos 'nome_do_diretório' '= [os.path.abspath (os.path.join (dir, i)) para i no os.listdir (dir)]"

HassanSh__3571619
fonte