Ler arquivos é uma das tarefas mais comuns em automação e administração de sistemas. No PowerShell, o cmdlet Get-Content é a ferramenta principal para essa finalidade, oferecendo flexibilidade para ler desde arquivos pequenos até logs gigantescos, com opções de controle de encoding e processamento linha a linha.

Nesta aula, vamos explorar a fundo o Get-Content, suas variações, como usar o parâmetro -Raw para leitura completa, como processar arquivos linha a linha de forma eficiente e como lidar com diferentes codificações de texto, essenciais para evitar erros de exibição ou processamento.

Get-Content

O cmdlet Get-Content é o equivalente PowerShell do comando cat do Linux, mas com muito mais recursos. Ele lê o conteúdo de um arquivo e o envia para o pipeline, permitindo que você manipule o texto diretamente. Por padrão, ele retorna um array de strings, onde cada elemento corresponde a uma linha do arquivo.

Vejamos um exemplo básico. Suponha que temos um arquivo chamado exemplo.txt com o seguinte conteúdo:

Get-Content -Path C:\Temp\exemplo.txt

Isso exibirá todas as linhas no console. O resultado é um array, então você pode armazená-lo em uma variável e acessar linhas específicas:

$linhas = Get-Content -Path C:\Temp\exemplo.txt
$linhas[0]  # primeira linha
$linhas[-1] # última linha

Além de -Path, você pode usar -LiteralPath quando o caminho contém caracteres curinga que não devem ser interpretados. O parâmetro -TotalCount permite ler apenas as primeiras N linhas, útil para inspecionar arquivos grandes sem carregar tudo na memória.

-Raw

O parâmetro -Raw altera o comportamento padrão: em vez de retornar um array de linhas, ele retorna o conteúdo completo do arquivo como uma única string, preservando as quebras de linha. Isso é útil quando você precisa tratar o arquivo como um bloco único, por exemplo, para fazer uma substituição global ou para passar o conteúdo para outro comando que espera uma string.

Exemplo:

$conteudo = Get-Content -Path C:\Temp\exemplo.txt -Raw
$conteudo -replace 'antigo', 'novo'

Com -Raw, a variável $conteudo contém todo o texto, incluindo as quebras de linha. Sem -Raw, o conteúdo seria um array de strings e o operador -replace funcionaria em cada linha separadamente, o que pode ser menos intuitivo para substituições que envolvem múltiplas linhas.

Outra vantagem é que -Raw é mais rápido para arquivos grandes, pois lê tudo de uma vez, enquanto o modo padrão precisa dividir em linhas. No entanto, para arquivos muito grandes, isso pode consumir muita memória, então é importante avaliar o contexto.

Lendo linha a linha

Processar arquivos linha a linha é essencial quando o arquivo é muito grande para caber na memória ou quando você deseja aplicar uma lógica de filtragem ou transformação em cada linha. O PowerShell oferece duas abordagens principais: usar o pipeline com ForEach-Object ou usar o loop foreach.

Com o pipeline, cada linha é enviada assim que é lida, permitindo processamento em streaming:

Get-Content -Path C:\Temp\log.txt | ForEach-Object {
    if ($_ -match 'erro') {
        Write-Host $_
    }
}

Essa abordagem é eficiente e idiomática no PowerShell. O mesmo pode ser feito com um loop tradicional, mas é menos eficiente porque carrega todas as linhas na memória antes de iterar:

$linhas = Get-Content -Path C:\Temp\log.txt
foreach ($linha in $linhas) {
    if ($linha -match 'erro') {
        Write-Host $linha
    }
}

Para arquivos muito grandes, a abordagem com pipeline é preferível, pois não armazena todas as linhas ao mesmo tempo. Outra alternativa é usar o método [System.IO.File]::ReadLines(), que retorna um enumerador que também processa linha a linha de forma eficiente.

Encoding

Encoding (ou codificação de caracteres) é um aspecto crítico ao ler arquivos. O PowerShell precisa saber como interpretar os bytes do arquivo para convertê-los em caracteres corretamente. Se o encoding especificado não corresponder ao real, você verá caracteres estranhos (como "�") ou erros de leitura.

O Get-Content possui o parâmetro -Encoding que permite especificar a codificação. Os valores mais comuns são: UTF8, UTF7, UTF32, ASCII, Unicode (UTF-16), BigEndianUnicode, Default (ANSI), e OEM. No PowerShell 7+, você também pode usar o nome completo do encoding, como utf-8 ou iso-8859-1.

Exemplo:

Get-Content -Path C:\Temp\arquivo.txt -Encoding UTF8

Se você não especificar, o PowerShell usa o encoding padrão, que no Windows PowerShell 5.1 é Default (ANSI), enquanto no PowerShell 7+ é UTF8 sem BOM. Para evitar problemas, é recomendável sempre especificar o encoding ao ler arquivos, especialmente se você sabe qual foi usado na criação.

Para descobrir o encoding de um arquivo, você pode usar o comando Format-Hex ou analisar os primeiros bytes (BOM). Por exemplo, um arquivo UTF-8 com BOM começa com os bytes EF BB BF.

Referências

Exercícios

  1. Crie um arquivo chamado teste.txt com três linhas: "Linha 1", "Linha 2", "Linha 3". Usando Get-Content, leia o arquivo e exiba a segunda linha.

    ✓ Resposta:
    $linhas = Get-Content -Path C:\Temp\teste.txt
    $linhas[1]  # Linha 2
  2. Leia o arquivo teste.txt usando -Raw e conte quantos caracteres ele possui (incluindo quebras de linha).

    ✓ Resposta:
    $conteudo = Get-Content -Path C:\Temp\teste.txt -Raw
    $conteudo.Length
  3. Escreva um script que leia um arquivo de log linha a linha e exiba apenas as linhas que contêm a palavra "erro". Use o pipeline com ForEach-Object.

    ✓ Resposta:
    Get-Content -Path C:\Temp\log.txt | ForEach-Object {
        if ($_ -match 'erro') {
            Write-Host $_
        }
    }
  4. Leia um arquivo com codificação UTF-8 explicitamente e exiba seu conteúdo no console. Explique por que é importante especificar o encoding.

    ✓ Resposta:
    Get-Content -Path C:\Temp\arquivo.txt -Encoding UTF8

    Especificar o encoding garante que os caracteres sejam interpretados corretamente. Se o arquivo estiver em UTF-8 e você não especificar, o PowerShell pode usar um encoding diferente (como ANSI), resultando em caracteres corrompidos.

  5. Use Get-Content com -TotalCount para ler apenas as duas primeiras linhas de um arquivo grande, sem carregar todo o arquivo na memória.

    ✓ Resposta:
    Get-Content -Path C:\Temp\grande.log -TotalCount 2

Boas Práticas e Observações Finais

Ao trabalhar com leitura de arquivos, sempre considere o tamanho do arquivo e o uso de memória. Para arquivos grandes, prefira o pipeline ou [System.IO.File]::ReadLines() para evitar estouro de memória. Sempre especifique o encoding quando souber, ou detecte-o antes de ler. Além disso, use -LiteralPath se o caminho contiver caracteres como colchetes ou curingas que possam ser interpretados erroneamente.

Outra dica: para arquivos com linhas muito longas, o Get-Content pode ser lento; considere usar StreamReader para controle mais fino. No entanto, para a maioria dos cenários, Get-Content é suficiente e mais simples.

Por fim, lembre-se de que o PowerShell 7+ tem diferenças em relação ao Windows PowerShell 5.1, principalmente no encoding padrão. Teste seus scripts em ambos se precisar de compatibilidade.