Ao trabalhar com arquivos em Python, é comum a necessidade de listar o conteúdo de diretórios. Duas funções primordiais do módulo os para essa tarefa são os.walk() e os.listdir(). Embora ambas listem arquivos e diretórios, elas diferem significativamente em sua abordagem e escopo.
1. Navegando em Estruturas de Diretório com os.walk()
A função os.walk() é ideal para percorrer recursivamente uma árvore de diretórios. Para cada diretório na árvore, a partir do caminho inicial especificado, ela gera uma tupla contendo três elementos: o caminho do diretório atual (root), uma lista dos nomes dos subdiretórios dentro desse caminho (dirs) e uma lista dos nomes dos arquivos não-diretório dentro desse caminho (files).
import os
def listar_arquivos_com_walk(diretorio_base):
"""
Lista recursivamente todos os arquivos e subdiretórios a partir de um diretório base.
"""
for raiz, subdiretorios, arquivos in os.walk(diretorio_base):
print(f"Diretório Atual: {raiz}")
print(f"Subdiretórios: {subdiretorios}")
print(f"Arquivos: {arquivos}")
print("-" * 20)
# Exemplo de uso:
# Supondo uma estrutura:
# .
# ├── script_principal.py
# ├── dados.txt
# ├── outro_dado.txt
# └── subpasta
# └── arquivo_sub.txt
# Se o script estiver em '.' e existir a estrutura acima:
# listar_arquivos_com_walk(".")
# Saída esperada (varia conforme a estrutura exata):
# Diretório Atual: .
# Subdiretórios: ['subpasta']
# Arquivos: ['dados.txt', 'outro_dado.txt', 'script_principal.py']
# --------------------
# Diretório Atual: ./subpasta
# Subdiretórios: []
# Arquivos: ['arquivo_sub.txt']
# --------------------
No exemplo acima, os.walk("./") primeiro processa o diretório raiz (./), listando seus subdiretórios (['test']) e arquivos (['200-2000(1).txt', ...]). Em seguida, ele desce para o subdiretório ./test, onde encontra apenas arquivos (['test.txt']) e nenhum subdiretório.
2. Listando Conteúdo de um Único Diretório com os.listdir()
Em contraste, os.listdir() retorna uma lista contendo os nomes de todas as entradas (arquivos e subdiretórios) diretamente dentro do caminho especificado. Ela não atravessa subdiretórios automaticamente.
import os
def listar_conteudo_diretorio(diretorio):
"""
Lista o conteúdo (arquivos e subdiretórios) de um único diretório.
"""
for nome_entrada in os.listdir(diretorio):
print(f"Entrada: {nome_entrada}")
# Exemplo de uso (considerando a mesma estrutura anterior):
# listar_conteudo_diretorio(".")
# Saída esperada:
# Entrada: dados.txt
# Entrada: outro_dado.txt
# Entrada: script_principal.py
# Entrada: subpasta
É importante notar que os.listdir() lista tanto arquivos quanto nomes de diretórios. No exemplo, 'subpasta' é listado como qualquer outro item no diretório atual.
3. Gerenciando Resultados: Variáveis Globais
Ao coletar nomes de arquivos de múltiplas chamadas de função ou de diferentes partes de um script, o uso de uma variável global pode ser uma abordagem para acumular todos os resultados.
import os
nomes_arquivos_globais = []
def adicionar_conteudo_global(diretorio):
"""
Adiciona os nomes de arquivos e diretórios de um diretório a uma lista global.
"""
for item in os.listdir(diretorio):
nomes_arquivos_globais.append(item)
# Supondo que '.' contenha 'arquivo1.txt', 'script.py', 'subpasta1'
# e './subpasta1' contenha 'arquivo_sub.txt'
# adicionar_conteudo_global(".")
# adicionar_conteudo_global("./subpasta1")
# print(f"Lista Global Completa: {nomes_arquivos_globais}")
# Lista Global Completa: ['arquivo1.txt', 'script.py', 'subpasta1', 'arquivo_sub.txt']
Neste cenário, nomes_arquivos_globais acumula os itens de cada diretório processado. Essa abordagem pode ser útil, mas pode levar a efeitos colaterais indesejados em programas maiores se o estado global não for gerenciado cuidadosmaente.
4. Coleta de Resultados: Variáveis Locais e Retorno de Função
Uma prática mais robusta e recomendada é utilizar variáveis locais dentro de funções e retornar os resultados. Isso encapsula o estado e torna a função mais reutilizável e testável.
import os
def obter_conteudo_local(diretorio):
"""
Retorna uma lista com os nomes de arquivos e diretórios de um diretório específico.
"""
itens_locais = []
for item in os.listdir(diretorio):
itens_locais.append(item)
return itens_locais
# Exemplo de uso:
# conteudo_diretorio_principal = obter_conteudo_local(".")
# conteudo_subpasta = obter_conteudo_local("./subpasta1")
# print(f"Conteúdo do diretório principal: {conteudo_diretorio_principal}")
# print(f"Conteúdo da subpasta: {conteudo_subpasta}")
# Saída esperada:
# Conteúdo do diretório principal: ['arquivo1.txt', 'script.py', 'subpasta1']
# Conteúdo da subpasta: ['arquivo_sub.txt']
Esta abordagem com variáveis locais e retorno explícito é geralmente preferível por promover um código mais limpo e modular.
5. Filtrando por Extensão com os.path.splitext()
Para obter apenas arquivos de um tipo específico, é possível combinar os.listdir() com os.path.splitext() para inspecionar a extensão de cada arquivo.
import os
def obter_arquivos_por_extensao(diretorio, extensao):
"""
Retorna uma lista de arquivos com a extensão especificada em um diretório.
"""
arquivos_filtrados = []
for nome_arquivo in os.listdir(diretorio):
# Verifica se é um arquivo e se a extensão corresponde
if os.path.isfile(os.path.join(diretorio, nome_arquivo)) and \
os.path.splitext(nome_arquivo)[1].lower() == extensao.lower():
arquivos_filtrados.append(nome_arquivo)
return arquivos_filtrados
# Exemplo de uso para obter arquivos .txt:
# arquivos_txt = obter_arquivos_por_extensao(".", ".txt")
# print(f"Arquivos .txt encontrados: {arquivos_txt}")
# Saída esperada (se houver arquivos .txt no diretório atual):
# Arquivos .txt encontrados: ['dados.txt', 'outro_dado.txt']
Esta técnica permite refinar a lista de arquivos retornada, focando apenas nos que atendem a um critério de extensão.