✂️ CLI Python para juntar e separar arquivos PDF com pikepdf.
PDF Split & Merge é uma ferramenta de linha de comando poderosa e simples para manipular arquivos PDF. Permite juntar múltiplos PDFs, extrair páginas específicas, dividir PDFs em arquivos individuais, comprimir e visualizar informações.
- ✅ Merge: Juntar múltiplos PDFs em um único arquivo
- ✅ Split: Extrair páginas específicas ou ranges (1-5, 1,3,5, etc.)
- ✅ Extract All: Separar cada página em arquivo individual
- ✅ Info: Visualizar metadados e informações do PDF
- ✅ Compress: Otimizar e reduzir tamanho do PDF
- ✅ Suporte a ranges complexos de páginas
- ✅ Validação de páginas
- ✅ Progress feedback visual
- ✅ Tratamento robusto de erros
- ✅ CLI intuitiva com Click
- Linguagem: Python 3.11+
- Biblioteca PDF: pikepdf
- CLI Framework: Click
- Testes: pytest + pytest-cov
- Linter: ruff
- Formatter: black
make installpip install -r requirements-dev.txtpython src/pdf_tool.py --help# Juntar dois PDFs
python src/pdf_tool.py merge file1.pdf file2.pdf -o merged.pdf
# Juntar múltiplos PDFs
python src/pdf_tool.py merge intro.pdf chapter1.pdf chapter2.pdf conclusao.pdf -o livro.pdf
# Juntar todos os PDFs do diretório
python src/pdf_tool.py merge *.pdf -o all.pdfSaída:
🔗 Juntando 3 arquivos PDF...
[1/3] Adicionando: file1.pdf
[2/3] Adicionando: file2.pdf
[3/3] Adicionando: file3.pdf
✅ Merge concluído com sucesso!
📄 Arquivo: merged.pdf
📊 Total de páginas: 45
# Extrair primeiras 5 páginas
python src/pdf_tool.py split input.pdf -p 1-5 -o first5.pdf
# Extrair páginas específicas
python src/pdf_tool.py split input.pdf -p 1,3,5,7,9 -o odd.pdf
# Extrair múltiplos ranges
python src/pdf_tool.py split input.pdf -p 1-10,20-30,40-50 -o selected.pdf
# Extrair uma única página
python src/pdf_tool.py split input.pdf -p 15 -o page15.pdfSaída:
📄 Abrindo: input.pdf
📊 Total de páginas no PDF original: 100
✅ Split concluído com sucesso!
📄 Arquivo: selected.pdf
📊 Páginas extraídas: 41
# Extrair cada página em arquivo separado
python src/pdf_tool.py extract-all input.pdf
# Com prefixo customizado
python src/pdf_tool.py extract-all input.pdf --prefix chapter
# Em diretório específico
python src/pdf_tool.py extract-all input.pdf --output-dir pages/Saída:
📄 Abrindo: input.pdf
📊 Total de páginas: 25
📁 Diretório de saída: /path/to/pages
[1/25] Criado: page_0001.pdf
[2/25] Criado: page_0002.pdf
...
[25/25] Criado: page_0025.pdf
✅ Extração concluída! 25 arquivos criados.
python src/pdf_tool.py info document.pdfSaída:
📄 Informações do PDF: document.pdf
==================================================
📊 Total de páginas: 120
📋 Metadados:
/Title: Meu Documento
/Author: João Silva
/CreationDate: 2025-01-15
🔢 Versão do PDF: 1.7
🔒 Criptografado: Não
💾 Tamanho do arquivo: 5.42 MB
==================================================
python src/pdf_tool.py compress large.pdf -o compressed.pdfSaída:
📄 Comprimindo: large.pdf
✅ Compressão concluída!
📄 Arquivo original: 10.50 MB
📄 Arquivo comprimido: 7.20 MB
📊 Redução: 31.4%
pdf-split-merge/
├── src/
│ └── pdf_tool.py # CLI principal com todos os comandos
├── tests/
│ └── test_pdf_tool.py # Testes unitários
├── requirements.txt # Dependências de produção
├── requirements-dev.txt # Dependências de desenvolvimento
├── Makefile
├── Dockerfile
├── .github/workflows/ci.yml
└── README.md
# Rodar testes
make test
# Testes com cobertura
pytest tests/ -v --cov=src --cov-report=html
# Ver relatório de cobertura
open htmlcov/index.html# Extrair apenas as páginas que precisam de assinatura
python src/pdf_tool.py split contrato_completo.pdf -p 1,15,30 -o para_assinar.pdf# Capítulo 1 (páginas 1-20)
python src/pdf_tool.py split livro.pdf -p 1-20 -o capitulo1.pdf
# Capítulo 2 (páginas 21-45)
python src/pdf_tool.py split livro.pdf -p 21-45 -o capitulo2.pdfpython src/pdf_tool.py merge \
intro.pdf \
modulo1.pdf \
modulo2.pdf \
modulo3.pdf \
conclusao.pdf \
-o treinamento_completo.pdf# Comprimir todos os PDFs de um diretório
for file in *.pdf; do
python src/pdf_tool.py compress "$file" -o "compressed_$file"
done# Criar PDF só com páginas ímpares
python src/pdf_tool.py split documento.pdf -p 1,3,5,7,9,11,13,15 -o impares.pdf# Build da imagem
make docker-build
# Merge via Docker
docker run --rm -v $(pwd):/output pdf-split-merge \
merge /output/file1.pdf /output/file2.pdf -o /output/merged.pdf
# Split via Docker
docker run --rm -v $(pwd):/output pdf-split-merge \
split /output/input.pdf -p 1-5 -o /output/first5.pdf
# Info via Docker
docker run --rm -v $(pwd):/output pdf-split-merge \
info /output/document.pdfO parâmetro -p ou --pages aceita:
| Formato | Exemplo | Descrição |
|---|---|---|
| Página única | 5 |
Apenas página 5 |
| Range | 1-10 |
Páginas 1 a 10 (inclusive) |
| Múltiplas páginas | 1,3,5 |
Páginas 1, 3 e 5 |
| Ranges combinados | 1-5,10-15,20 |
Páginas 1-5, 10-15 e 20 |
Importante: As páginas são 1-indexed (primeira página = 1).
A ferramenta valida automaticamente:
- ✅ Arquivos PDF existem
- ✅ Páginas estão dentro do range válido
- ✅ Ranges são válidos (start ≤ end)
- ✅ Pelo menos 2 arquivos para merge
- ✅ Sintaxe correta de ranges
- Não remove senhas de PDFs criptografados (pikepdf requer senha)
- Não processa formulários PDF interativos
- Compressão depende do conteúdo (imagens já comprimidas não reduzem muito)
- Extract all pode criar muitos arquivos (cuidado com PDFs de 1000+ páginas)
- Suporte a PDFs criptografados (com senha)
- Rotacionar páginas
- Adicionar marca d'água
- Adicionar numeração de páginas
- Converter imagens para PDF
- Modo batch (processar múltiplos PDFs via config file)
- Interface web simples (Flask)
Para processar muitos PDFs:
# Paralelizar com GNU parallel
parallel python src/pdf_tool.py compress {} -o compressed_{} ::: *.pdfCriar script de backup:
#!/bin/bash
# backup-pdfs.sh
python src/pdf_tool.py merge documents/*.pdf -o "backup_$(date +%Y%m%d).pdf"# .github/workflows/process-pdfs.yml
- name: Merge release documents
run: |
pip install pikepdf click
python pdf_tool.py merge docs/*.pdf -o release.pdfMIT License - veja LICENSE
- Faça fork do projeto
- Crie uma branch para sua feature (
git checkout -b feature/nova-feature) - Commit suas mudanças (
git commit -m 'Adiciona nova feature') - Push para a branch (
git push origin feature/nova-feature) - Abra um Pull Request
Encontrou um bug? Abra uma issue com:
- Versão do Python
- Comando executado
- Erro completo
- PDF de exemplo (se possível)