Linux / Comando tac: inverter linhas e escolher separadores
O comando tac envia os registros de cada arquivo à saída padrão, do último para o primeiro. O separador padrão é a quebra de linha: ele inverte a ordem das linhas, mantendo os caracteres de cada registro. Isso permite ler um log de baixo para cima, mas não ordena eventos pelas datas escritas no texto.
Os exemplos usam Bash e GNU Coreutils e criam arquivos pequenos em uma pasta exclusiva sob a pasta atual. Execute a preparação no mesmo terminal e pare se houver erro. Para o exemplo com paginação, o programa less também precisa estar instalado; as demais práticas imprimem resultados diretamente.
O nome é cat escrito ao contrário. Um registro é o trecho delimitado pelo separador escolhido; por padrão, o separador fica associado ao fim do registro anterior. Vários arquivos são processados na ordem dos operandos, com a inversão feita em cada um separadamente, conforme o manual GNU de tac. Sem arquivos, ou com o operando -, a entrada vem da entrada padrão.
Sintaxe básica
tac [opções]... [arquivo]...
opções e arquivo são marcadores. Use aspas em caminhos com espaços e -- antes de nomes que possam parecer opções. Para um arquivo chamado literalmente -, use ./-. Confira tac --version, tac --help e man tac no sistema de destino; extensões GNU podem não existir em outra implementação.
Uso básico do tac
Inverter as linhas de um arquivo
A preparação cria um log com quatro linhas em ordem crescente de horário, dois arquivos mensais, cópias de demonstração para navegação e pesquisa, registros com outro separador e um arquivo de controle. No fim, tac mostra o log começando por 09:30 ERROR ultima e terminando por 09:00 INFO inicio. Os horários são dados inventados para o exemplo, não registros de um serviço real.
tac_start=$PWD
tac_demo=$(mktemp -d -p "$PWD" 'tac-demo.XXXXXXXX') &&
cd -- "$tac_demo" &&
printf '09:00 INFO inicio\n09:10 ERROR primeira\n09:20 INFO meio\n09:30 ERROR ultima\n' > events.log &&
printf 'jan-1\njan-2\n' > january.log &&
printf 'fev-1\nfev-2\n' > february.log &&
cat -- events.log > application.log &&
cat -- events.log > access.log &&
printf 'um---dois---tres---' > records.txt &&
printf 'controle intacto\n' > sentinel.txt &&
tac -- events.log
Processar vários arquivos
O resultado é jan-2, jan-1, fev-2, fev-1, uma linha por item. Janeiro continua antes de fevereiro. Para inverter uma única sequência formada pela junção dos dois arquivos, a operação seria cat -- january.log february.log | tac; nesse caso, as linhas de fevereiro vêm primeiro. Isso ainda não compara datas ou combina registros por horário.
cd -- "$tac_demo" &&
tac -- january.log february.log
Inverter a entrada padrão
Um pipe liga a saída do primeiro comando à entrada do seguinte. O printf abaixo fornece três linhas e termina; tac devolve tres, dois, um. O fim da entrada precisa ser conhecido antes de começar a inversão. Uma entrada não posicionável, como um pipe, pode exigir armazenamento temporário, detalhado nos cuidados abaixo.
printf 'um\ndois\ntres\n' | tac
Conferir o resultado da inversão
As palavras permanecem inteiras: o comando troca a ordem dos registros, não a ordem das letras de cada um. O próximo bloco produz exatamente as três linhas mostradas no bloco de saída; não execute o bloco de saída como se fosse um comando.
printf 'primeiro\nsegundo\nterceiro\n' | tac
Saída esperada:
terceiro
segundo
primeiro
A quebra de linha faz parte do registro por padrão. Se a entrada for primeiro, uma quebra de linha e ultimo sem quebra final, a saída será ultimoprimeiro e uma quebra de linha. Nenhum separador é criado para completar o trecho final. Esse detalhe explica por que dois textos podem aparecer juntos; não é uma inversão das letras.
Principais opções
| Opção | Efeito |
|---|---|
-s TEXTO |
Usar TEXTO como separador literal, em vez da quebra de linha. Um argumento vazio, -s '', seleciona o byte NUL (de valor zero) no GNU tac. |
-b |
Associar o separador ao início do registro seguinte, em vez de ao fim do anterior. Isso pode mudar a posição dos separadores na saída. |
-r |
Interpretar o separador como expressão regular. Use aspas para que o shell não altere o padrão antes de tac recebê-lo. |
--help |
Consultar as opções da implementação instalada. |
Exemplos práticos
Navegar pelo log em ordem inversa
O arquivo de demonstração tem as mesmas quatro linhas do primeiro log. A saída invertida é entregue ao paginador less, que permite navegar e pesquisar; normalmente q encerra a visualização e /ERROR, seguido de Enter, pesquisa o texto. Essas teclas seguem a configuração do paginador. Para acompanhar novas linhas sem esperar o fim do fluxo, use a abordagem de tail, como tail -f, em vez de alimentar tac indefinidamente.
cd -- "$tac_demo" &&
tac -- application.log | less
Comparar separadores literais e expressões regulares
O arquivo records.txt contém um---dois---tres---, sem quebra de linha. A primeira chamada retorna tres---dois---um---. A segunda chamada recebe outra entrada, ---um---dois---tres, com cada registro precedido por seu separador. Nesse caso, -b produz ---tres---dois---um. Use essa opção quando o separador pertencer ao começo do registro; aplicá-la a dados delimitados no fim pode criar junções ou registros vazios inesperados. Os dois printf com uma quebra apenas separam os resultados na tela; não fazem parte dos dados. A última chamada usa [|#] como expressão regular que encontra um de dois separadores e produz c#b#a|. Esses exemplos não acrescentam automaticamente uma quebra final.
cd -- "$tac_demo" &&
tac -s '---' -- records.txt &&
printf '\n' &&
printf '%s' '---um---dois---tres' | tac -b -s '---' &&
printf '\n' &&
printf 'a|b#c#' | tac -r -s '[|#]'
Encontrar a última linha que contém um texto
No arquivo preparado, o resultado é 09:30 ERROR ultima. O grep com -F procura o texto literal e -m 1 para após uma linha selecionada, conforme o controle de saída do GNU Grep. Trata-se da última ocorrência na ordem física das linhas. Se o arquivo estiver fora de ordem cronológica ou um evento ocupar várias linhas, esse método não identifica automaticamente o evento mais recente nem preserva seu contexto completo.
cd -- "$tac_demo" &&
tac -- access.log | grep -F -m 1 -- 'ERROR'
Comparar tac e outros comandos
| Comando | Função principal | Quando usar |
|---|---|---|
tac |
Inverter a sequência atual dos registros | Ler do último registro para o primeiro |
cat |
Manter a sequência dos dados | Exibir e concatenar arquivos |
tail |
Selecionar a parte final ou acompanhar acréscimos | Ler poucas linhas finais ou monitorar um log |
sort -r |
Comparar valores e inverter a ordem de classificação | Ordenar pelo conteúdo; não apenas inverter posições |
Cuidados importantes
Distinguir posição, horário e limites de registros
A inversão usa separadores, sem interpretar datas, fusos ou a estrutura de um log. Mensagens com várias linhas podem ficar fragmentadas quando a unidade é uma linha. Com um separador personalizado, confirme em dados conhecidos o que pertence ao início ou ao fim de cada registro. Preserve uma cópia independente antes de substituir qualquer original; nunca use tac arquivo > arquivo, pois o shell pode esvaziar o arquivo antes da leitura. Nomes diferentes também podem apontar ao mesmo objeto por links.
Considerar o fim da entrada e o espaço temporário
Para um arquivo regular que permita reposicionar a leitura, a implementação pode ler a partir do fim; isso não equivale a uma varredura cronológica. Entradas não posicionáveis precisam ser armazenadas até o fim. O manual GNU documenta o uso de TMPDIR, com recurso a /tmp quando a variável não está definida ou o local não está disponível. Um fluxo enorme pode consumir espaço em disco; um fluxo que nunca termina não fornece o fim necessário. Não use tail -f ... | tac como monitor de linhas invertidas. As práticas deixam os arquivos para inspeção; volte com cd -- "$tac_start".
Conferir a implementação e os estados de saída
As opções e os exemplos seguem GNU tac; outra implementação pode ter diferenças. Em pipelines, o Bash usa por padrão o estado do último comando. O sucesso de grep não comprova sozinho que tac leu tudo sem erro. Além disso, quando grep -m 1 fecha o pipe cedo, o produtor pode falhar ao continuar escrevendo; pipefail pode tornar isso visível. Para automações importantes, trate separadamente falhas de leitura, ausência de correspondência e encerramento antecipado, sem concluir que todo estado diferente de zero significa arquivo corrompido.
Perguntas frequentes
tac e sort -r são equivalentes?
Não. tac inverte as posições dos registros na sequência existente. sort -r compara os conteúdos segundo suas regras e opções de classificação. Uma simples inversão não garante que os registros fiquem em ordem cronológica.
Como inverter somente as últimas dez linhas?
Use tail -n 10 -- arquivo.log | tac com um arquivo sob seu controle. Primeiro são selecionadas até dez linhas finais; depois sua ordem é invertida. Confira os limites dos registros e os estados dos dois comandos quando isso fizer parte de uma automação.
tac acompanha um log em tempo real?
Não é adequado para um fluxo sem fim: a inversão depende de conhecer o final da entrada. Use tail -f para acompanhar acréscimos e uma ferramenta que entenda o formato dos eventos quando precisar ordenar ou agrupar mensagens.
Vários arquivos são unidos antes da inversão?
Não. Em tac -- a.log b.log, cada arquivo é invertido separadamente, mantendo a ordem dos operandos. Em cat -- a.log b.log | tac, tac recebe uma única sequência concatenada, que é invertida como um todo. Nenhuma das formas ordena datas automaticamente.




