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.

8 min de leitura Equipe Python Brasil

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:

  1. O operador / funciona mesmo entre um Path e uma str — ele monta o caminho na sintaxe correta do sistema operacional.
  2. No Linux e macOS você recebe um PosixPath; no Windows, um WindowsPath. Você não escolhe: o pathlib decide sozinho, e o mesmo código roda nas duas plataformas.
  3. 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çãoos.path (legado)pathlib (moderno)
Juntar caminhoos.path.join("a", "b.txt")Path("a") / "b.txt"
Caminho absolutoos.path.abspath(p)p.resolve()
Existe?os.path.exists(p)p.exists()
É arquivo?os.path.isfile(p)p.is_file()
Nome do arquivoos.path.basename(p)p.name
Pasta-paios.path.dirname(p)p.parent
Extensãoos.path.splitext(p)[1]p.suffix
Nome sem extensãoos.path.splitext(p)[0]p.stem
Tamanho em bytesos.path.getsize(p)p.stat().st_size
Listar pastaos.listdir(pasta)pasta.iterdir()
Busca recursivaos.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 encoding ao ler ou gravar texto (read_text(encoding="utf-8")). No Windows, o padrão costuma ser cp1252; em arquivos com acentos, o UTF-8 evita UnicodeDecodeError.
  • Use .resolve() antes de comparar caminhos absolutos — dois caminhos diferentes na string podem apontar para o mesmo arquivo depois de resolvidos.
  • Prefira .glob/.rglob ao os.walk para buscas por padrão; reserve os.walk para percorrimentos com lógica de filtro complexa.
  • Não corte extensões com string slicing. Use .suffix e .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.

E

Equipe Python Brasil

Contribuidor do Python Brasil — Aprenda Python em Português