pathlib em Python: O Guia Prático para Manipular Caminhos e Arquivos
Aprenda a usar o módulo pathlib do Python para manipular caminhos, listar arquivos com glob e rglob, ler e escrever com read_text e write_text, criar e remover pastas e migrar do os.path. Guia prático em português brasileiro com exemplos de automação de arquivos.
O pathlib é o módulo da biblioteca padrão do Python para trabalhar com caminhos de arquivos e pastas. Ele substitui, com vantagem, as velhas funções do os.path (os.path.join, os.path.exists, os.path.basename), oferecendo um objeto Path com métodos e atributos prontos para as operações mais comuns do dia a dia: listar arquivos, ler e escrever conteúdo, criar pastas, percorrer subdiretórios com glob e montar caminhos de forma legível. Desde o Python 3.12 o próprio os.path é implementado internamente sobre o pathlib, o que reforça o pathlib como a API oficial e moderna para caminhos.
Se você já automatiza planilhas CSV, documentos Word ou arquivos ZIP, dominar o pathlib é o que transforma scripts avulsos em pipelines robustos que percorrem pastas inteiras. Este guia parte do objeto Path e chega a receitas práticas de automação brasileira, com uma comparação direta contra o os.path no final.
Criando um caminho com Path
Tudo começa importando Path e construindo um caminho. O pathlib usa o operador / para juntar partes — o que é muito mais legível do que os.path.join("a", "b", "c.txt"):
from pathlib import Path
# Caminho relativo na pasta do projeto
pasta_dados = Path("dados")
arquivo = pasta_dados / "vendas" / "2026.csv"
print(arquivo) # dados/vendas/2026.csv (no Linux/macOS)
# dados\vendas\2026.csv (no Windows)
print(type(arquivo)) # <class 'pathlib.PosixPath'> (ou WindowsPath no Windows)
Repare em três detalhes importantes:
- O operador
/funciona mesmo entre umPathe umastr— ele monta o caminho na sintaxe correta do sistema operacional. - No Linux e macOS você recebe um
PosixPath; no Windows, umWindowsPath. Você não escolhe: opathlibdecide sozinho, e o mesmo código roda nas duas plataformas. - Para transformar um caminho relativo em absoluto (com a pasta raiz resolvida), use
.resolve():
print(Path("dados/2026.csv").resolve())
# /home/maria/projetos/dados/2026.csv
Atributos de um caminho: nome, extensão, pasta-pai
Um dos grandes ganhos do pathlib é acessar pedaços do caminho por atributos claros, sem ficar cortando string:
p = Path("/home/maria/projetos/dados/2026.csv")
p.name # '2026.csv' — nome do arquivo
p.stem # '2026' — nome sem a extensão
p.suffix # '.csv' — extensão (com o ponto)
p.suffixes # ['.tar', '.gz'] — lista de extensões (para .tar.gz)
p.parent # /home/maria/projetos/dados
p.parents[0] # mesmo que .parent
p.parents[1] # /home/maria/projetos
p.parts # ('/', 'home', 'maria', 'projetos', 'dados', '2026.csv')
p.anchor # '/' (ou 'C:\\' no Windows)
Esses atributos resolvem, sem esforço, tarefas chatas como trocar a extensão de um arquivo (p.with_suffix(".txt")) ou pegar só o nome da pasta:
p.with_suffix(".txt") # /home/maria/projetos/dados/2026.txt
p.with_name("resumo.md") # /home/maria/projetos/dados/resumo.md
Verificações: o arquivo existe? É arquivo ou pasta?
Antes de ler ou apagar qualquer coisa, verifique. O pathlib traz os métodos booleanos mais usados:
arquivo = Path("notas_fiscais/2026-07.xml")
arquivo.exists() # True/False — o caminho existe no disco?
arquivo.is_file() # é um arquivo (não uma pasta)?
arquivo.is_dir() # é uma pasta?
arquivo.is_absolute() # é um caminho absoluto?
Para um script de automação que processa arquivos, o padrão defensivo é:
arquivo = Path("config.yaml")
if not arquivo.exists():
raise FileNotFoundError(f"Configuração não encontrada: {arquivo}")
Listando arquivos: iterdir, glob e rglob
Esta é a funcionalidade que mais economiza tempo. Para percorrer o conteúdo de uma pasta:
pasta = Path("relatorios")
# Tudo que está diretamente dentro da pasta (arquivos e subpastas)
for item in pasta.iterdir():
print(item.name)
Para filtrar por padrão, use .glob(). Ele aceita curingas como * e ?, mas não desce nas subpastas:
# Apenas arquivos .csv no primeiro nível
for csv in pasta.glob("*.csv"):
print(csv)
Para percorrer a pasta e todas as subpastas recursivamente, use .rglob():
# Todos os arquivos .xlsx em qualquer nível de profundidade
for planilha in pasta.rglob("*.xlsx"):
print(planilha)
É com .rglob() que você constrói, em três linhas, um processador de arquivos do escritório inteiro:
from pathlib import Path
import csv
pasta = Path("vendas")
for arquivo in pasta.rglob("*.csv"):
with arquivo.open(encoding="utf-8") as f:
linhas = sum(1 for _ in f)
print(f"{arquivo.name}: {linhas} linhas")
Lendo e escrevendo arquivos com read_text e write_text
Para ler ou gravar um arquivo inteiro de uma vez, o pathlib oferece atalhos que dispensam o open com with:
p = Path("config.txt")
# Escrever (sobrescreve o arquivo)
p.write_text("timeout=30\n", encoding="utf-8")
# Ler
conteudo = p.read_text(encoding="utf-8")
print(conteudo)
Esses métodos abrem, leem/escrevem e fecham o arquivo automaticamente. Para processar linha a linha, gravar incrementalmente ou lidar com arquivos muito grandes, continue usando .open() (equivalente ao open tradicional dentro de um with) — veja o tutorial de manipulação de arquivos e o de context managers com with.
# Leitura linha a linha para arquivos grandes
with Path("log.txt").open(encoding="utf-8") as f:
for linha in f:
if "ERRO" in linha:
print(linha.strip())
Criando, movendo, copiando e removendo
Operações de sistema de arquivos ficam expressivas no pathlib:
from pathlib import Path
import shutil
pasta = Path("saida")
arquivo = pasta / "relatorio.txt"
# Criar uma pasta (exist_ok=True evita erro se já existir)
pasta.mkdir(parents=True, exist_ok=True)
# Criar um arquivo vazio (se não existir)
arquivo.touch()
# Copiar (o pathlib delega ao shutil para cópia)
shutil.copy("entrada.txt", arquivo)
# Renomear / mover
arquivo.rename(pasta / "relatorio_final.txt")
# Remover o arquivo
(pasta / "relatorio_final.txt").unlink()
# Remover a pasta (precisa estar vazia)
pasta.rmdir()
O mkdir(parents=True, exist_ok=True) equivale a mkdir -p do Linux: cria pastas intermediárias e não reclama se a pasta já existe. É a forma recomendada de preparar diretórios de saída.
Receita brasileira: organizar notas fiscais por mês
Um caso de uso concreto que une tudo: você recebe dezenas de XMLs de NF-e soltos numa pasta e quer organizá-los em subpastas por mês de emissão. Com pathlib e tratamento de datas, o script fica enxuto:
from pathlib import Path
from datetime import datetime
pasta_entrada = Path("xmls_recebidos")
pasta_saida = Path("xmls_organizados")
for xml in pasta_entrada.glob("*.xml"):
# Extrai a data do nome (padrão: NF_2026-07-18_12345.xml)
try:
data_str = xml.stem.split("_")[1] # '2026-07-18'
mes = datetime.strptime(data_str, "%Y-%m-%d").strftime("%Y-%m")
except (IndexError, ValueError):
mes = "sem_data"
destino = pasta_saida / mes
destino.mkdir(parents=True, exist_ok=True)
xml.rename(destino / xml.name) # move o arquivo
print("Organização concluída.")
O mesmo molde serve para separar comprovantes em PDF, agrupar imagens de produtos por SKU ou consolidar planilhas por filial. Sempre que você precisar “varrer uma pasta e reagrupar por regra”, comece com .rglob() + .mkdir() + .rename().
pathlib vs os.path: qual usar em 2026?
Se você mantém código legado com os.path, não precisa reescrever — as duas APIs coexistem. Em projetos novos, porém, o pathlib é a recomendação oficial da documentação do Python. A tabela resume as equivalências mais comuns:
| Operação | os.path (legado) | pathlib (moderno) |
|---|---|---|
| Juntar caminho | os.path.join("a", "b.txt") | Path("a") / "b.txt" |
| Caminho absoluto | os.path.abspath(p) | p.resolve() |
| Existe? | os.path.exists(p) | p.exists() |
| É arquivo? | os.path.isfile(p) | p.is_file() |
| Nome do arquivo | os.path.basename(p) | p.name |
| Pasta-pai | os.path.dirname(p) | p.parent |
| Extensão | os.path.splitext(p)[1] | p.suffix |
| Nome sem extensão | os.path.splitext(p)[0] | p.stem |
| Tamanho em bytes | os.path.getsize(p) | p.stat().st_size |
| Listar pasta | os.listdir(pasta) | pasta.iterdir() |
| Busca recursiva | os.walk(pasta) | pasta.rglob("*") |
A regra prática: se você está escrevendo a versão moderna de um script, use pathlib; se está lendo um tutorial antigo com os.path, entenda a equivalência mas prefira converter para pathlib ao refatorar.
Boas práticas
- Sempre informe o
encodingao ler ou gravar texto (read_text(encoding="utf-8")). No Windows, o padrão costuma sercp1252; em arquivos com acentos, o UTF-8 evitaUnicodeDecodeError. - Use
.resolve()antes de comparar caminhos absolutos — dois caminhos diferentes na string podem apontar para o mesmo arquivo depois de resolvidos. - Prefira
.glob/.rglobaoos.walkpara buscas por padrão; reserveos.walkpara percorrimentos com lógica de filtro complexa. - Não corte extensões com string slicing. Use
.suffixe.with_suffix()— eles respeitam arquivos como.tar.gz. - Valide a entrada antes de mover/apagar. Um
if not arquivo.exists()custa pouco e evita acidentes em automações que rodam em produção.
Conclusão
O pathlib é uma daquelas partes do Python que, uma vez aprendidas, mudam a forma como você escreve código para sempre. O objeto Path concentra nome, extensão, pasta-pai e verificação de existência em atributos legíveis; .glob e .rglob substituem loops inteiros de os.walk; e read_text/write_text deixam a leitura e escrita simples em uma linha. Para qualquer automação que envolva arquivos — da organização de notas fiscais ao processamento de planilhas em lote — comece pelo pathlib.
Para continuar a sequência de fundamentos da biblioteca padrão, veja como combinar pathlib com collections para contar e agrupar arquivos, com expressões regulares para renomear em massa, e com o módulo subprocess para chamar ferramentas externas sobre os caminhos encontrados.
Perguntas frequentes
O pathlib vem instalado com o Python ou preciso instalar algo?
O pathlib faz parte da biblioteca padrão do Python desde a versão 3.4 e não precisa ser instalado com o pip — basta fazer from pathlib import Path. A partir do Python 3.12 o módulo os.path é implementado internamente sobre o pathlib, o que reforça o pathlib como a API oficial e moderna para trabalhar com caminhos.
Qual a diferença entre pathlib e os.path?
O os.path manipula caminhos como strings e usa funções soltas como os.path.join e os.path.exists. O pathlib representa o caminho como um objeto Path, com métodos e atributos encadeáveis (p.suffix, p.parent, p.read_text()) e suporta o operador /. O resultado é um código mais legível e orientado a objetos; em projetos novos, prefira pathlib.
Como listar apenas arquivos .csv de uma pasta e suas subpastas com pathlib?
Use Path('pasta').rglob('*.csv'), que percorre a pasta e todas as subpastas. Para listar só o primeiro nível, sem descer nas subpastas, use Path('pasta').glob('*.csv'). Ambos retornam objetos Path que podem ser iterados diretamente com um for.
Como o pathlib lida com caminhos no Windows e no Linux ao mesmo tempo?
O pathlib normaliza o separador automaticamente: ao usar o operador / ou Path(), ele usa a barra correta do sistema (\ no Windows, / no Linux e macOS). O mesmo código funciona nas duas plataformas sem if. Para um caminho absoluto, use Path.resolve(), que resolve o caminho completo no sistema atual.
read_text e write_text substituem o open com with?
Para a leitura e escrita simples de um arquivo inteiro, sim. Path('arquivo.txt').read_text(encoding='utf-8') abre, lê e fecha o arquivo automaticamente. Para processar linha a linha, gravar incrementalmente ou lidar com arquivos muito grandes, continue usando open com with, como no tutorial de manipulação de arquivos.
Equipe Python Brasil
Contribuidor do Python Brasil — Aprenda Python em Português