Path.walk() é um método da biblioteca pathlib para percorrer diretórios de forma estruturada, usando objetos Path em vez de strings. Ele simplifica tarefas como inventariar arquivos, localizar extensões, aplicar filtros, calcular tamanhos, remover diretórios vazios e organizar rotinas de backup. Neste guia, você aprenderá como usar Path.walk() com segurança, entender seus parâmetros e evitar armadilhas comuns.
O que é Path.walk()
O método walk() percorre uma árvore de diretórios e produz, a cada passo, uma tupla com três elementos: o diretório atual, a lista de subdiretórios e a lista de arquivos. A ideia é semelhante a os.walk(), mas integrada ao estilo orientado a objetos de pathlib.
from pathlib import Path
raiz = Path("projeto")
for diretorio, subdirs, arquivos in raiz.walk():
print(diretorio)
print(subdirs)
print(arquivos)O primeiro item é um objeto Path. Já os nomes em subdirs e arquivos são strings relativas ao diretório atual. Para obter o caminho completo, combine o diretório com o nome usando o operador /.
for diretorio, subdirs, arquivos in raiz.walk():
for nome in arquivos:
caminho = diretorio / nome
print(caminho)Por que usar pathlib em vez de strings
Trabalhar com Path deixa o código mais legível e portátil. Em vez de concatenar separadores manualmente, você usa o operador /. Métodos como suffix, name, stem, stat() e is_file() ficam disponíveis diretamente no objeto.
Essa abordagem combina bem com outras práticas de Python moderno. Consulte também nossos guias sobre importlib.resources no Python, fileinput no Python, linecache no Python e contextlib.chdir no Python.
Listando todos os arquivos
Um dos usos mais comuns é gerar uma lista de arquivos existentes em uma árvore. O exemplo abaixo ignora diretórios e reúne apenas arquivos.
from pathlib import Path
raiz = Path("dados")
arquivos_encontrados = []
for diretorio, subdirs, arquivos in raiz.walk():
for nome in arquivos:
arquivos_encontrados.append(diretorio / nome)
for caminho in arquivos_encontrados:
print(caminho)Para árvores muito grandes, evite acumular todos os caminhos em uma lista. Processe cada arquivo durante a própria iteração para reduzir o uso de memória.
Filtrando por extensão
Você pode filtrar arquivos por sufixo usando Path.suffix. Para comparações previsíveis, converta a extensão para minúsculas.
for diretorio, subdirs, arquivos in Path("logs").walk():
for nome in arquivos:
caminho = diretorio / nome
if caminho.suffix.lower() == ".log":
print(caminho)Para várias extensões, use um conjunto, pois a consulta é eficiente e o código fica claro.
extensoes = {".csv", ".json", ".parquet"}
for diretorio, subdirs, arquivos in Path("dados").walk():
for nome in arquivos:
caminho = diretorio / nome
if caminho.suffix.lower() in extensoes:
processar(caminho)Controlando a ordem da travessia
O parâmetro top_down define se a árvore é percorrida de cima para baixo ou de baixo para cima. O padrão é True. Nesse modo, o diretório pai aparece antes dos filhos.
for diretorio, subdirs, arquivos in Path("projeto").walk(top_down=True):
print(diretorio)Com top_down=False, os diretórios mais profundos são visitados primeiro. Esse modo é útil ao remover diretórios vazios, pois os filhos precisam ser tratados antes dos pais.
for diretorio, subdirs, arquivos in Path("temporario").walk(top_down=False):
if not subdirs and not arquivos:
diretorio.rmdir()Ignorando pastas específicas
Quando top_down=True, você pode alterar a lista subdirs no lugar para impedir que certos diretórios sejam visitados. Isso é mais eficiente do que entrar na pasta e descartar os resultados depois.
ignoradas = {".git", ".venv", "node_modules", "__pycache__"}
for diretorio, subdirs, arquivos in Path("projeto").walk():
subdirs[:] = [nome for nome in subdirs if nome not in ignoradas]
for nome in arquivos:
print(diretorio / nome)A atribuição subdirs[:] modifica a lista original recebida pelo mecanismo de travessia. Criar apenas uma nova variável não altera o percurso.
Tratando erros com on_error
Permissões insuficientes, diretórios removidos durante a execução e falhas de entrada e saída podem interromper a travessia. O parâmetro on_error recebe uma função para tratar a exceção.
def registrar_erro(erro):
print(f"Não foi possível acessar: {erro.filename}")
for diretorio, subdirs, arquivos in Path("/").walk(on_error=registrar_erro):
passEm aplicações reais, prefira registrar o erro com contexto e continuar apenas quando isso for seguro. Não ignore silenciosamente todas as exceções, porque você pode gerar inventários incompletos sem perceber.
Links simbólicos
O comportamento relacionado a links simbólicos merece atenção. Seguir links para diretórios pode criar ciclos, especialmente quando um link aponta para um ancestral. Antes de habilitar esse comportamento, defina uma estratégia para evitar visitas repetidas.
Em rotinas críticas, registre os caminhos já visitados ou use identificadores do sistema de arquivos quando necessário. Também verifique se a aplicação deve atravessar links externos à raiz original. Em backups e scanners, isso pode causar leitura de locais inesperados.
Calculando o tamanho de uma árvore
O método pode ser usado para somar o tamanho dos arquivos. O exemplo trata arquivos que desaparecem entre a listagem e a chamada a stat().
from pathlib import Path
def tamanho_total(raiz: Path) -> int:
total = 0
for diretorio, subdirs, arquivos in raiz.walk():
for nome in arquivos:
caminho = diretorio / nome
try:
total += caminho.stat().st_size
except OSError:
continue
return total
print(tamanho_total(Path("dados")))Em ambientes concorrentes, a árvore pode mudar durante a execução. Por isso, resultados devem ser entendidos como uma fotografia aproximada, não como uma transação atômica.
Localizando arquivos grandes
Você pode combinar walk() com stat() para encontrar arquivos acima de um limite.
limite = 500 * 1024 * 1024
for diretorio, subdirs, arquivos in Path("arquivos").walk():
for nome in arquivos:
caminho = diretorio / nome
try:
if caminho.stat().st_size > limite:
print(caminho)
except OSError as erro:
print(f"Falha ao ler {caminho}: {erro}")Evite apagar arquivos automaticamente apenas com base no tamanho. Gere um relatório, valide o caminho e aplique regras de retenção explícitas.
Comparação com rglob()
rglob() é excelente quando você quer encontrar caminhos por padrão, como *.py. Já walk() oferece mais controle sobre a travessia, incluindo poda de diretórios, tratamento de erros e ordem de visita.
for caminho in Path("projeto").rglob("*.py"):
print(caminho)Use rglob() para buscas simples e walk() quando precisar tomar decisões sobre cada diretório.
Comparação com os.walk()
os.walk() continua válido e amplamente usado. A principal diferença é o estilo. Com Path.walk(), o diretório atual já é um objeto Path, o que reduz conversões e melhora a integração com outras operações da biblioteca.
Em projetos antigos, não é necessário migrar imediatamente. Faça a mudança quando ela simplificar o código e quando a versão mínima do Python usada pelo projeto oferecer suporte ao método.
Boas práticas de desempenho
Evite chamar stat() várias vezes para o mesmo arquivo. Se precisar de tamanho, datas e permissões, armazene o resultado em uma variável. Também filtre diretórios o mais cedo possível e processe arquivos em fluxo.
Para árvores muito grandes, considere limites de profundidade implementados por você. walk() não recebe diretamente um parâmetro de profundidade máxima, mas você pode comparar a quantidade de partes do caminho atual com a raiz e limpar subdirs quando atingir o limite.
raiz = Path("dados")
max_niveis = 3
for diretorio, subdirs, arquivos in raiz.walk():
profundidade = len(diretorio.relative_to(raiz).parts)
if profundidade >= max_niveis:
subdirs.clear()Segurança em operações destrutivas
Travessias de diretório costumam aparecer em scripts de limpeza. Antes de excluir, mover ou sobrescrever arquivos, valide se o caminho está dentro da raiz esperada. Use resolve() com cuidado e considere condições de corrida em sistemas multiusuário.
Uma estratégia segura é separar descoberta e execução. Primeiro produza um relatório; depois revise; por fim execute as alterações com logs e possibilidade de recuperação.
Compatibilidade
Como Path.walk() foi adicionado em versões recentes do Python, verifique a versão mínima do seu projeto. Para ambientes antigos, use os.walk() ou implemente uma camada de compatibilidade.
Consulte a documentação oficial de pathlib e a documentação de os.walk para detalhes atualizados de parâmetros e comportamento.
Conclusão
Path.walk() oferece uma forma moderna e expressiva de percorrer árvores de diretórios. Ele combina controle de travessia, integração com objetos Path, filtragem eficiente e tratamento de erros. Ao usá-lo, pense em permissões, links simbólicos, alterações concorrentes e impacto de operações destrutivas. Com esses cuidados, o método se torna uma base sólida para inventários, backups, validadores, pipelines de dados e ferramentas de manutenção.







