Scripts e automação de arquivos

Combinar arquivos CSV e manter os nomes dos arquivos de origem

Combine em ordem arquivos CSV com a mesma estrutura de colunas e adicione uma coluna source_file. Use conjuntos de dados pequenos para verificar nomes de itens com vírgulas, colunas ausentes e saídas já existentes.

Ver o sumário

A tradução foi feita com IA. Confira o código, as unidades e os valores junto com o original. A revisão por falantes nativos de cada idioma ainda não foi concluída. English

Para quem éIniciantes em Python que querem combinar em uma única tabela arquivos CSV de diferentes datas ou pessoas.

Preparação
  • Instale o Python 3.12 ou posterior e confira a versão em um terminal com python --version.
  • Extraia o ZIP de exemplo para uma nova pasta. Não execute o exemplo de dentro do arquivo ZIP.
  • Abra um terminal na pasta que contém example.py. Se o comando python não estiver disponível no Windows, use py. No macOS ou Linux, use python3 se o seu ambiente exigir.
  • Não são necessários pacotes externos nem contas. Os arquivos incluídos são dados sintéticos criados para este tutorial.

01Combine dois arquivos em cinco linhas

Se os números parecerem errados depois de combinar arquivos, pode ser difícil rastrear de onde vieram. Este exemplo mantém as quatro colunas originais e adiciona source_file no final. O objetivo é identificar diretamente o nome do arquivo original em cada linha do resultado. Primeiro, some as 2 e 3 linhas de dados dos arquivos de entrada e anote o total esperado de 5.

  1. Localize inputs/sales_01.csv e inputs/sales_02.csv na pasta extraída.
  2. Abra os dois arquivos em um editor de texto e confira se a primeira linha é date,item,quantity,unit_price.
  3. Execute o comando abaixo em um terminal aberto na pasta que contém example.py.
  4. Abra outputs/merged.csv e confira se há cinco linhas de dados e a coluna source_file.
bash
python example.py

Manter as pastas de entrada e saída separadas evita que um merged.csv anterior seja usado como entrada em uma execução posterior. O código também localiza inputs em relação a example.py. Se você mantiver a estrutura de pastas ao extrair o ZIP, não precisará alterar os caminhos.

02Faça a estrutura das colunas coincidir antes de combinar

Coluna de entradaValor de exemploComo este exemplo trata o valor
date2026-09-01Mantido como texto
item노트Mantido, incluindo vírgulas e aspas
quantity2Mantido como texto, sem cálculo
unit_price2500Mantido como texto, sem cálculo

Tanto os nomes das colunas quanto a ordem precisam coincidir. Por exemplo, o script para se um arquivo usar qty no lugar de quantity ou mover unit_price para outra posição. Ele não tenta adivinhar o significado nem alinhar colunas automaticamente, permitindo perceber quando formatos de departamentos diferentes foram misturados.

Os dados sintéticos incluem “메모지, 대형” (bloco de notas grande) e “표지 "파랑"” (capa "azul"), que contém aspas duplas. Ler CSV simplesmente usando split por vírgulas pode separar esses valores nos campos errados. Deixe o módulo padrão csv tratar as regras de aspas e depois grave novamente as linhas conforme foram lidas.

03Código completo usado neste exemplo

collect_rows verifica o cabeçalho e as linhas de cada CSV e adiciona o nome do arquivo original. Somente depois que todas as verificações passam é que main cria uma nova saída. Essa ordem evita deixar uma combinação parcial dos primeiros arquivos quando um arquivo posterior tem colunas incorretas.

example.py
"""inputs의 같은 구조 CSV를 결합합니다. 각 행에 원본 파일명을 붙입니다."""

import csv
import sys
from pathlib import Path

BASE = Path(__file__).resolve().parent
INPUT = BASE / "inputs"
OUTPUT = BASE / "outputs"
FIELDS = ["date", "item", "quantity", "unit_price"]


def collect_rows():
    if INPUT.is_symlink() or not INPUT.is_dir():
        raise ValueError("inputs 폴더가 없거나 링크입니다.")
    if getattr(INPUT, "is_junction", lambda: False)():
        raise ValueError("연결 디렉터리는 처리하지 않습니다.")
    # inputs 바로 아래의 .csv 파일만 읽습니다. 순서를 명시해 결과를 재현합니다.
    paths = sorted(
        (p for p in INPUT.iterdir() if p.suffix.lower() == ".csv"),
        key=lambda p: p.name.casefold(),
    )
    if not paths:
        raise ValueError("inputs에 CSV 파일이 없습니다.")
    merged = []
    counts = []
    for path in paths:
        if path.is_symlink() or not path.is_file():
            raise ValueError(f"일반 CSV 파일이 아닙니다: {path.name}")
        with path.open("r", encoding="utf-8-sig", newline="") as stream:
            reader = csv.DictReader(stream, strict=True)
            if reader.fieldnames != FIELDS:
                raise ValueError(f"{path.name}: 열 이름과 순서는 {FIELDS}여야 합니다.")
            count = 0
            for row in reader:
                # 열이 많으면 None 키, 적으면 None 값이 생깁니다.
                if None in row or any(value is None or not value.strip() for value in row.values()):
                    raise ValueError(f"{path.name}, {reader.line_num}행: 열 수 또는 빈 값을 확인하세요.")
                merged.append({**row, "source_file": path.name})
                count += 1
            counts.append((path.name, count))
    return merged, counts


def main():
    if OUTPUT.exists() or OUTPUT.is_symlink():
        raise FileExistsError("outputs가 이미 있습니다. 기존 결과를 옮긴 뒤 실행하세요.")
    rows, counts = collect_rows()  # 모든 파일을 검증한 다음에 출력합니다.
    OUTPUT.mkdir()
    target = OUTPUT / "merged.csv"
    with target.open("x", encoding="utf-8-sig", newline="") as stream:
        writer = csv.DictWriter(stream, fieldnames=FIELDS + ["source_file"])
        writer.writeheader()
        writer.writerows(rows)
    for name, count in counts:
        print(f"{name}: {count}행")
    print(f"완료: {len(counts)}개 파일 → {len(rows)}행")
    print(target)
    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except (OSError, ValueError, csv.Error) as error:
        print(f"중지: {error}", file=sys.stderr)
        raise SystemExit(2)

As verificações usam o comportamento do DictReader de adicionar uma chave None quando há campos de dados demais e um valor None quando há campos de menos. Strings vazias e valores contendo apenas espaços também são rejeitados. Definir newline como string vazia e especificar uma codificação compatível com BOM UTF-8 mantém consistente o tratamento de quebras de linha e texto em coreano.

04Compare tanto a quantidade de linhas quanto os arquivos de origem

Ordem da linha no resultadoitemquantitysource_file
1노트2sales_01.csv
2펜3sales_01.csv
3노트1sales_02.csv
4메모지, 대형4sales_02.csv
5표지 "파랑"1sales_02.csv

O terminal mostra “sales_01.csv: 2행” (duas linhas), “sales_02.csv: 3행” (três linhas) e “완료: 2개 파일 → 5행” (concluído: dois arquivos → cinco linhas), nessa ordem. O cabeçalho da primeira linha não é contado como dado. Ver 노트 (caderno) duas vezes não é um erro. As duas linhas originais são mantidas; nenhum total foi calculado e nenhuma duplicata foi removida.

05Faça quatro verificações antes de confiar no resultado

  1. Confira se a soma das linhas de entrada, 5, corresponde ao número de linhas de dados do resultado.
  2. Confira se duas linhas têm source_file definido como sales_01.csv e três como sales_02.csv.
  3. Confira se o nome de item que contém uma vírgula continua em uma única célula e se as aspas duplas não desapareceram.
  4. Abra novamente os dois arquivos originais e confirme que o conteúdo não foi alterado. Confira também se executar o script novamente faz a execução parar porque outputs já existe.

No trabalho real, verificar a quantidade de linhas é diferente de verificar totais. Mesmo que os totais monetários coincidam por acaso, uma linha pode estar faltando e outra pode estar duplicada. Como esta etapa não realiza cálculos, comece comparando as contagens por origem e o texto original.

06Pratique adicionando um terceiro arquivo

Antes de executar novamente, renomeie a primeira pasta outputs para mantê-la. Adicione sales_03.csv dentro de inputs com o mesmo cabeçalho e uma linha de dados. A quantidade esperada de dados é seis. Confira se a nova linha tem sales_03.csv em source_file para observar como a adição de uma entrada afeta a coluna de rastreamento.

Somente arquivos com extensão .csv diretamente dentro de inputs são incluídos. O script não pesquisa subpastas recursivamente nem combina notas de texto ou pastas de trabalho do Excel. Se nenhum arquivo CSV for encontrado, ele trata isso como uma seleção incorreta de entrada e para. Um CSV válido contendo apenas o cabeçalho conta como 0 linhas e não impede que os outros arquivos sejam combinados.

07Verifique os erros em vez de aceitar resultados parciais

Motivo da interrupçãoOnde verificarComo corrigir
Os nomes ou a ordem das colunas não coincidemA primeira linha do arquivo indicadoFaça as quatro colunas obrigatórias coincidirem exatamente.
Quantidade incorreta de campos ou valor vazioO nome do arquivo e o número de linha informadoVerifique campos ausentes, delimitadores extras e valores vazios.
Erro de aspas no CSVUma aspa dupla não fechadaUse uma cópia com a estrutura corrigida em um editor de CSV.
Erro de codificaçãoA codificação em que o arquivo de entrada foi salvoCrie uma cópia exportada em UTF-8.
outputs already existsA pasta de resultados anteriorMova os resultados e execute novamente.

Os números de linha dos erros se referem às linhas físicas lidas do CSV. Em arquivos CSV complexos com quebras de linha dentro de valores entre aspas, eles podem ser diferentes dos números de linhas de dados em uma planilha. Use primeiro o nome do arquivo mostrado na mensagem para localizar a origem.

08Onde termina a combinação e começa a validação dos dados

Este script verifica a estrutura das colunas, valores vazios e a sintaxe do CSV. Ele não determina se quantity é numérico, se date é uma data válida ou se os valores atendem às regras do seu trabalho. Se você precisar fazer cálculos depois de uma combinação simples, adicione conversão numérica e verificações de faixa permitida como etapas separadas de validação.

Todas as linhas são coletadas na memória e salvas após a validação, então este exemplo é adequado para praticar com arquivos de trabalho pequenos. Arquivos CSV muito grandes exigem um projeto com saída temporária e processamento em etapas. Um erro de disco durante a gravação pode deixar resultados parciais; não considere a execução bem-sucedida sem uma mensagem de conclusão. Alterações simultâneas nos arquivos de entrada e falhas em caminhos de rede estão fora do escopo desta verificação.

Registro de execução e verificação

2026-09-19 · Windows 11 · CPython 3.12.14 · Sem pacotes adicionais · Executado em uma cópia temporária da distribuição

  • Foram combinados 2 arquivos CSV em 5 linhas e conferidas as contagens de source_file
  • Foram preservadas células contendo vírgulas e aspas duplas
  • Cabeçalhos incorretos, campos ausentes ou extras, valores vazios e aspas malformadas foram rejeitados antes da criação da saída
  • Foi verificado o tratamento de arquivos CSV somente com cabeçalho e da ausência de arquivos CSV
  • Foi confirmado que os hashes SHA-256 dos arquivos originais permaneceram inalterados e que a saída existente foi preservada
Limites da verificação
  • O uso de memória com arquivos grandes não foi medido.
  • O significado de negócio de números e datas não é validado.
  • A execução foi verificada no Windows.

Princípios de redação e verificação de todo o site

Arquivos de exemplo para executar

Inclui código, dados de entrada e instruções de execução. Extraia o ZIP e leia primeiro o README.txt.

Baixar ZIP de exemplo

O código de exemplo, os nomes de arquivos e as chaves de entrada são mantidos como no original. Consulte também os comandos e os procedimentos de conferência do texto traduzido.

Material de prática original · Guarde os arquivos originais separadamente antes de executar.

Fontes de referência

As explicações e os exemplos são de elaboração própria. Os comportamentos e conceitos relacionados podem ser consultados nas fontes oficiais abaixo.