CodeGym /Cursos /C# SELF /Operações em massa com arquivos

Operações em massa com arquivos

C# SELF
Nível 40 , Lição 4
Disponível

1. Introdução

Imagine um arquivo com fotos acumuladas ao longo de vários anos — milhares de arquivos numa única pasta (clássico do usuário Windows), e agora pense na tarefa: copiar só os arquivos .jpg que foram criados este ano para uma pasta separada para processamento. Ou você precisa renomear todos os relatórios com o prefixo "old_" pra diferenciar versão antiga da nova. Mesmo que você esteja longe de arquivos de fotos, operações em massa aparecem em praticamente qualquer projeto que lide com dados, logs, backups ou automação. Também costumam cair em entrevistas!

Operações em massa são uma ótima oportunidade pra pegar:

  • Loops e LINQ pra percorrer o conteúdo de diretórios
  • Prática com caminhos (Path)
  • Fundamentos de filtragem, busca e renomeação em padrão
  • Questões importantes: segurança, erros, sobrescritas

Bora — e que a força esteja com você pra derrotar o caos dos arquivos!

2. Cópia em massa de arquivos

Como funciona: princípio geral

Pra uma operação em massa normalmente você precisa:

  1. Obter a lista de arquivos desejados (por exemplo, todos os .txt numa pasta)
  2. Pra cada arquivo executar a ação necessária (cópia, exclusão, etc.)

Isso pode ser feito com:

  • Directory.GetFiles() — pra pegar a lista de arquivos,
  • Loop foreach — pra iterar cada arquivo e fazer a operação.

Exemplo: copiar todos os arquivos .txt de uma pasta para outra


string sourceDir = @"C:\Source";
string destDir = @"C:\Target";

// Obtemos a lista de todos os .txt na pasta de origem
string[] txtFiles = Directory.GetFiles(sourceDir, "*.txt");

foreach (string srcPath in txtFiles)
{
    // Pega só o nome do arquivo a partir do caminho completo
    string fileName = Path.GetFileName(srcPath);

    // Monta o caminho completo para o arquivo na pasta destino
    string destPath = Path.Combine(destDir, fileName);

    // Copia o arquivo
    File.Copy(srcPath, destPath, overwrite: true); // overwrite - se o arquivo já existir, substituir
    Console.WriteLine($"Copied: {fileName}");
}

Console.WriteLine("Todos os arquivos .txt foram copiados com sucesso!");

Repare: neste exemplo usamos o filtro "*.txt" — é um pattern de busca de nomes de arquivos, igual ao do Windows.

Visualização (diagrama)

+----------------+     [*.txt]     +----------------+
|   C:\Source    | ---filter-----> |   C:\Target    |
| a.txt          |   foreach +     |                |
| b.txt          | --copy--------> | a.txt (copied) |
| c.jpg          |                | b.txt (copied) |
+----------------+                +----------------+
(.jpg arquivos são ignorados, só .txt são copiados)

3. Exclusão em massa de arquivos

Exclusão em massa é uma operação bem comum. Por exemplo, é frequente limpar arquivos temporários, apagar logs antigos ou fotos jpg que você não precisa mais.

Exemplo: deletar todos os arquivos com mais de 30 dias


string dir = @"C:\MyLogs";
int daysOld = 30;

DirectoryInfo di = new DirectoryInfo(dir);
// Pega todos os arquivos na pasta
foreach (FileInfo file in di.GetFiles())
{
    // Verifica a data da última modificação
    if (file.LastWriteTime < DateTime.Now.AddDays(-daysOld))
    {
        file.Delete();
        Console.WriteLine($"Deleted: {file.Name}");
    }
}

Dica: FileInfo.LastWriteTime é bem útil pra condição "mais velho que N dias".

4. Renomeação em massa de arquivos

Às vezes é preciso renomear muitos arquivos por um padrão. Por exemplo, adicionar um prefixo em comum, trocar extensões, ou numerar tudo sequencialmente. Em .NET isso também é feito pegando a lista de arquivos e então renomeando com File.Move().

Exemplo: adicionar o prefixo "old_" a todos os arquivos .docx


string dir = @"C:\Reports";

string[] docxFiles = Directory.GetFiles(dir, "*.docx");
foreach (string oldPath in docxFiles)
{
    string dirPath = Path.GetDirectoryName(oldPath)!;
    string fileName = Path.GetFileName(oldPath);
    string newPath = Path.Combine(dirPath, "old_" + fileName);

    // Renomeia (na prática é um move "pra mesma pasta com nome novo")
    File.Move(oldPath, newPath);
    Console.WriteLine($"Renamed: {fileName} -> old_{fileName}");
}

Ponto importante: se já existir um arquivo com o novo nome, vai lançar exceção. Dá pra tratar com try-catch quando necessário.

5. Copiar diretórios inteiros com todo o conteúdo

Para operações simples com uma pasta não existe um método "copiar pasta" numa linha (Directory.Copy não existe — pegadinha de jedi!). É preciso copiar manualmente:

  1. Criar a pasta destino (se não existir)
  2. Copiar todos os arquivos (veja o exemplo conhecido)
  3. Recursivamente copiar todas as subpastas (cada uma tratada como nova tarefa de cópia)

Função genérica: copiar pasta recursivamente


using System;
using System.IO;

class Program
{
    static void CopyDirectory(string sourceDir, string destDir, bool overwrite = true)
    {
        // Cria a pasta se ela não existir
        Directory.CreateDirectory(destDir);

        // Copia todos os arquivos
        foreach (string filePath in Directory.GetFiles(sourceDir))
        {
            string fileName = Path.GetFileName(filePath);
            string destFile = Path.Combine(destDir, fileName);
            File.Copy(filePath, destFile, overwrite);
        }

        // Copia todas as subpastas (recursivamente)
        foreach (string subDir in Directory.GetDirectories(sourceDir))
        {
            string dirName = Path.GetFileName(subDir);
            string destSubDir = Path.Combine(destDir, dirName);
            CopyDirectory(subDir, destSubDir, overwrite);
        }
    }

    static void Main()
    {
        string source = @"C:\Archive2023";
        string target = @"D:\Backup2023";
        CopyDirectory(source, target);
        Console.WriteLine("Diretório copiado com sucesso!");
    }
}

Fluxograma

            CopyDirectory(A, B)
               /          \
      copy files        foreach subDir -> CopyDirectory(subDir, destSubDir)

6. Filtragem em massa, busca e processamento de arquivos

Suponha que você queira não só iterar uma pasta, mas selecionar por vários critérios: por exemplo, só imagens cujo tamanho é maior que 5 MB e que foram criadas em 2024! Pra isso é legal combinar LINQ com as classes do sistema de arquivos.

Exemplo: listar nomes de imagens grandes e recentes


string dir = @"C:\Pictures";

var filtered = new DirectoryInfo(dir)
    .GetFiles("*.jpg")
    .Where(f => f.Length > 5_000_000 && f.CreationTime.Year == 2024);

foreach (var file in filtered)
{
    Console.WriteLine($"{file.Name} ({file.Length / 1024 / 1024} MB)");
}

Nesse exemplo usamos LINQ pra encadear filtros — e escrevemos código realista, do dia a dia.

7. Percorrendo pastas aninhadas: recursão e iteração

Muitas vezes é preciso processar não só uma pasta, mas todas as subpastas (por exemplo, apagar todos os arquivos temporários na árvore de um backup). Os métodos de obtenção de arquivos (Directory.GetFiles e DirectoryInfo.GetFiles) têm uma opção com o parâmetro SearchOption.AllDirectories, que faz isso pra você!

Exemplo: encontrar e deletar todos os arquivos .tmp em todas as subpastas


string root = @"D:\BigFolder";
string[] tmpFiles = Directory.GetFiles(root, "*.tmp", SearchOption.AllDirectories);

foreach (string file in tmpFiles)
{
    File.Delete(file);
    Console.WriteLine($"Deleted: {file}");
}
Console.WriteLine("Todos os arquivos temporários foram deletados.");

Atenção: tome cuidado com esse flag — ele pode encontrar arquivos em profundidades muito grandes!

8. Criação em massa de arquivos e diretórios

Às vezes a tarefa é o inverso — criar automaticamente uma estrutura de diretórios ou gerar muitos arquivos.

Exemplo: criar 10 pastas e 10 arquivos em cada


string root = @"C:\GeneratedFolders";

for (int i = 1; i <= 10; i++)
{
    string subDir = Path.Combine(root, $"Folder_{i}");
    Directory.CreateDirectory(subDir);

    for (int j = 1; j <= 10; j++)
    {
        string filePath = Path.Combine(subDir, $"File_{j}.txt");
        File.WriteAllText(filePath, $"Este é o arquivo número {j} na pasta {i}");
    }
}

Console.WriteLine("Pastas e arquivos criados!");

Dica: dá pra montar rapidamente uma infra de teste, gerar "mock" pra testes, aprendizado, etc.

9. Movimentação em massa de arquivos

Semelhante à cópia, só que usamos File.Move em vez de File.Copy. Ótimo pra organizar arquivos em pastas.

Exemplo: organizar arquivos por extensão

Imagine: numa pasta tem um monte de arquivos de vários tipos, e você quer separá-los em pastas .jpg, .pdf, .docx etc.


string source = @"C:\Downloads";
string[] files = Directory.GetFiles(source);

foreach (string path in files)
{
    string ext = Path.GetExtension(path).TrimStart('.').ToUpper(); // "JPG", "PDF", "DOCX"
    if (string.IsNullOrEmpty(ext)) ext = "OTHER";
    string destDir = Path.Combine(source, ext);

    Directory.CreateDirectory(destDir); // sem problema se já existir

    string fileName = Path.GetFileName(path);
    string destPath = Path.Combine(destDir, fileName);

    if (!File.Exists(destPath))
    {
        File.Move(path, destPath);
        Console.WriteLine($"Moved: {fileName} -> {destDir}");
    }
    else
    {
        Console.WriteLine($"Arquivo já existe em {destDir}, pulando: {fileName}");
    }
}

Os arquivos vão se espalhar por "caixinhas" e você vai se sentir um Marie Kondo digital.

10. Erros típicos e nuances de operações em massa

Quando você trabalha não com um arquivo, mas com centenas, aparecem detalhes interessantes.

Por exemplo, alguns arquivos podem estar abertos por outro programa — tentar deletar ou copiar vai gerar erro. Também é comum que já exista um arquivo com o nome alvo na pasta destino. Se o fluxo não prevê sobrescrita, o código vai falhar com exceção. Às vezes pode faltar permissão em arquivos ou pastas, ou você pode acidentalmente deletar algo importante recursivamente.

Erro clássico é executar operações sem tratamento de erros: se algo falhar no meio (por exemplo, falta de permissão em um arquivo), o loop vai quebrar e as ações seguintes não vão acontecer. Por isso, pra operações em massa confiáveis geralmente se usa tratamento de exceções com try-catch dentro do loop, pra pular o arquivo problemático e continuar processando os outros.

E não esqueça dos parâmetros de sobrescrita: onde for apropriado, use overwrite: true em File.Copy, e ao renomear/mover verifique antes se já existe um arquivo no caminho destino ou adote uma estratégia de conflito (renomear com sufixo, pular, logar).

1
Pesquisa/teste
Criação e exclusão de arquivos, nível 40, lição 4
Indisponível
Criação e exclusão de arquivos
Gerenciamento de arquivos e diretórios
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION