Percorrer árvores de diretórios é uma tarefa comum em automações, ferramentas de linha de comando, sistemas de backup e organizadores de arquivos. Durante muito tempo, a solução mais conhecida no Python foi os.walk(). A partir do Python 3.12, porém, a classe Path do módulo pathlib passou a oferecer o método Path.walk(), que combina a navegação recursiva com uma API orientada a objetos. Neste guia, você vai aprender como usar pathlib.Path.walk no Python, entender as diferenças em relação a os.walk() e aplicar o recurso em scripts reais.
O que é pathlib.Path.walk?
Path.walk() percorre uma árvore de diretórios e gera, a cada etapa, uma tupla com três valores: o diretório atual, uma lista com os nomes das subpastas e uma lista com os nomes dos arquivos. A estrutura é parecida com a de os.walk(), mas o primeiro elemento é um objeto Path, o que facilita operações posteriores como juntar caminhos, verificar extensões e abrir arquivos.
from pathlib import Path
raiz = Path("projeto")
for diretorio, pastas, arquivos in raiz.walk():
print("Diretório:", diretorio)
print("Pastas:", pastas)
print("Arquivos:", arquivos)
Se você ainda não conhece o módulo, vale revisar o artigo sobre manipulação de arquivos com pathlib. Ele apresenta a base necessária para entender objetos Path, junção de caminhos e leitura de arquivos.
Como montar o caminho completo
Os nomes de arquivos retornados aparecem como strings. Para obter o caminho completo, combine o diretório atual com cada nome usando o operador / do pathlib.
from pathlib import Path
for diretorio, pastas, arquivos in Path("dados").walk():
for nome in arquivos:
caminho = diretorio / nome
print(caminho)
Esse padrão é simples e evita concatenações manuais com barras. Ele também funciona de forma portátil em Windows, macOS e Linux. Para entender melhor problemas de caminhos inválidos, consulte o guia sobre FileNotFoundError no Python.
Filtrando arquivos por extensão
Um uso frequente é localizar apenas arquivos de determinado tipo. Como o caminho completo é um objeto Path, você pode usar a propriedade suffix.
from pathlib import Path
for diretorio, pastas, arquivos in Path("relatorios").walk():
for nome in arquivos:
arquivo = diretorio / nome
if arquivo.suffix.lower() == ".csv":
print(arquivo)
Esse script encontra arquivos CSV em todas as subpastas. A chamada a lower() permite reconhecer extensões como .CSV. Para processar o conteúdo depois da busca, veja também o tutorial sobre arquivos CSV no Python.
Ignorando pastas durante a busca
Quando a caminhada ocorre de cima para baixo, você pode alterar a lista pastas diretamente. Isso impede que o método entre em diretórios desnecessários, como ambientes virtuais, cache e dependências instaladas.
from pathlib import Path
ignoradas = {".git", ".venv", "__pycache__", "node_modules"}
for diretorio, pastas, arquivos in Path("meu_projeto").walk(top_down=True):
pastas[:] = [p for p in pastas if p not in ignoradas]
print(diretorio)
A atribuição com pastas[:] modifica a lista original usada internamente pela caminhada. Criar apenas uma nova variável não produz o mesmo efeito. Esse controle reduz o tempo de execução e evita acessar diretórios enormes sem necessidade.
top_down e bottom_up
O parâmetro top_down define a ordem da travessia. O valor padrão é True, portanto o diretório pai é produzido antes dos filhos. Com False, os diretórios mais profundos aparecem primeiro.
from pathlib import Path
for diretorio, pastas, arquivos in Path("temporarios").walk(top_down=False):
print(diretorio)
A ordem de baixo para cima é útil ao excluir uma árvore de diretórios, porque os arquivos e pastas internas precisam ser removidos antes da pasta principal. Já a ordem de cima para baixo é melhor quando você deseja filtrar subdiretórios antes de visitá-los.
Tratando erros de acesso
Durante a varredura, o programa pode encontrar diretórios sem permissão. O argumento on_error recebe uma função chamada quando ocorre um erro de sistema.
from pathlib import Path
def registrar_erro(erro):
print(f"Não foi possível acessar: {erro.filename}")
for diretorio, pastas, arquivos in Path("/dados").walk(on_error=registrar_erro):
print(diretorio)
Sem esse manipulador, determinados erros podem ser ignorados conforme o comportamento documentado. Em scripts críticos, registrar a falha é melhor do que assumir que todos os diretórios foram analisados. O artigo sobre PermissionError no Python ajuda a diagnosticar permissões incorretas.
Contando arquivos e calculando tamanho
Você pode combinar walk() com stat() para produzir um resumo do armazenamento.
from pathlib import Path
quantidade = 0
total_bytes = 0
for diretorio, pastas, arquivos in Path("backup").walk():
for nome in arquivos:
caminho = diretorio / nome
try:
total_bytes += caminho.stat().st_size
quantidade += 1
except OSError as erro:
print("Falha:", caminho, erro)
print("Arquivos:", quantidade)
print("Tamanho:", total_bytes, "bytes")
O tratamento de OSError é importante porque um arquivo pode ser removido ou ter suas permissões alteradas entre a listagem e a leitura dos metadados.
Diferenças entre Path.walk e os.walk
As duas funções seguem uma lógica parecida, mas há diferenças práticas. Path.walk() retorna um objeto Path como raiz de cada etapa, enquanto os.walk() retorna strings. Além disso, o tratamento de links simbólicos e a classificação de entradas podem ter detalhes diferentes. Por isso, não faça uma substituição automática sem testar o script.
A documentação oficial de Path.walk descreve os parâmetros e o comportamento com links simbólicos. A referência de os.walk é útil para comparar as duas APIs.
Links simbólicos e segurança
O parâmetro follow_symlinks controla se links simbólicos para diretórios devem ser percorridos. O padrão é False. Ativá-lo exige cuidado, porque um link pode apontar para um diretório pai e criar um ciclo. O método não mantém automaticamente um histórico completo de diretórios visitados para evitar toda recursão circular.
from pathlib import Path
for diretorio, pastas, arquivos in Path("dados").walk(follow_symlinks=False):
pass
Em ferramentas de backup ou limpeza, manter o valor padrão costuma ser mais seguro. Caso seja necessário seguir links, registre caminhos resolvidos e implemente uma proteção contra ciclos.
Exemplo: organizar arquivos por extensão
O exemplo abaixo percorre uma pasta de entrada e move arquivos para subpastas baseadas na extensão.
from pathlib import Path
import shutil
origem = Path("entrada")
destino = Path("organizados")
for diretorio, pastas, arquivos in origem.walk():
for nome in arquivos:
arquivo = diretorio / nome
extensao = arquivo.suffix.lower().lstrip(".") or "sem_extensao"
pasta_destino = destino / extensao
pasta_destino.mkdir(parents=True, exist_ok=True)
shutil.move(str(arquivo), pasta_destino / arquivo.name)
Antes de executar em arquivos importantes, teste com cópias. Movimentações podem causar sobrescritas ou conflitos de nome. O tutorial sobre copiar e mover arquivos com shutil apresenta cuidados adicionais.
Boas práticas
Defina claramente a raiz antes de caminhar, filtre diretórios cedo, trate erros de sistema e evite seguir links simbólicos sem necessidade. Em árvores muito grandes, processe cada resultado conforme ele é produzido em vez de armazenar todos os caminhos em uma lista. Também prefira comparar extensões em minúsculas e valide operações destrutivas com um modo de simulação.
Conclusão
pathlib.Path.walk oferece uma maneira moderna e legível de percorrer diretórios no Python. Ele se integra naturalmente à API do pathlib, permite controlar a ordem da travessia, ignorar pastas e tratar erros. Para projetos que usam Python 3.12 ou superior, é uma alternativa excelente a os.walk(). O ponto principal é combinar a praticidade da API com verificações de segurança, especialmente em scripts que movem, alteram ou excluem arquivos.







