De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Rubens Queiroz de Almeida
Data de Publicação: 26 de agosto de 2026
O comando sort costuma ser apresentado apenas como uma ferramenta para colocar linhas em ordem alfabética. Em scripts e rotinas de administração, porém, seus recursos mais interessantes estão na criação de chaves complexas, ordenações estáveis, processamento de arquivos extensos, controle de localidade, mesclagem de dados previamente ordenados e tratamento seguro de nomes de arquivos.
Este tutorial parte do princípio de que o leitor já conhece comandos básicos como:
$ sort arquivo $ sort -n numeros.txt $ sort -r arquivo
Nosso foco será explorar situações em que a escolha incorreta das opções pode produzir resultados discretamente errados.
Por padrão, o sort compara linhas completas segundo as regras da localidade ativa:
$ sort arquivo.txt
A ordenação pode ser influenciada por variáveis como:
LANG LC_ALL LC_COLLATE LC_NUMERIC LC_TIME
Confira a configuração:
$ locale
LC_COLLATE determina as regras de comparação textual. LC_NUMERIC influencia a interpretação dos números e LC_TIME afeta recursos como a ordenação pelos nomes dos meses.
Para obter uma comparação baseada nos valores dos bytes:
$ LC_ALL=C sort arquivo.txt
Essa forma possui duas vantagens importantes em scripts:
Compare:
$ printf '%s\n' \
ação \
arvore \
Árvore \
casa |
sort
com:
$ printf '%s\n' \
ação \
arvore \
Árvore \
casa |
LC_ALL=C sort
Os resultados podem ser diferentes porque a primeira execução aplica as regras linguísticas da localidade atual, enquanto a segunda compara a representação dos caracteres.
Em scripts que alimentam outros comandos, use frequentemente:
$ LC_ALL=C sort
Em relatórios destinados à leitura humana, a localidade do usuário pode produzir uma ordem mais natural.
A opção -k define uma chave:
-k INÍCIO,FIM
Cada posição pode ser especificada como:
CAMPO.CARACTERE
Por exemplo:
$ sort -k2.3,2.7 arquivo.txt
Essa chave:
Quando a posição do caractere é omitida, são usados estes padrões:
Assim:
$ sort -k2,2 arquivo.txt
usa somente o segundo campo.
Já:
$ sort -k2 arquivo.txt
usa tudo desde o início do segundo campo até o fim da linha.
Essa diferença é uma das causas mais comuns de resultados inesperados.
As opções de comparação podem ser globais:
$ sort -n -k3,3 arquivo.txt
ou associadas diretamente à chave:
$ sort -k3,3n arquivo.txt
A segunda forma é mais clara quando existem múltiplas chaves com regras diferentes.
Considere servidores.txt:
web02 producao 32 98.7 db01 producao 128 74.2 web01 homologacao 16 31.5 db02 producao 64 74.2 web03 homologacao 32 45.0
Os campos representam:
Para ordenar alfabeticamente pelo ambiente e numericamente pela memória, em ordem decrescente:
$ sort \-k2,2 \ -k3,3nr \ servidores.txt
O modificador nr pertence somente à segunda chave.
Para acrescentar o nome do servidor como desempate:
$ sort \
-k2,2 \
-k3,3nr \
-k1,1 \
servidores.txt
Essa forma deixa explícita toda a hierarquia da ordenação.
Quando todas as chaves informadas são iguais, o GNU sort normalmente usa a linha completa como último critério de desempate.
Considere:
10 Carlos 10 Ana 10 Beatriz
Execute:
$ sort -k1,1n arquivo.txt
Embora a chave numérica seja igual, os nomes poderão ser reorganizados:
10 Ana 10 Beatriz 10 Carlos
Isso acontece porque as linhas completas são usadas no desempate.
Para preservar a ordem original entre chaves iguais, use ordenação estável:
$ sort -s -k1,1n arquivo.txt
Resultado:
10 Carlos 10 Ana 10 Beatriz
A opção -s, de *stable*, desativa o desempate final pela linha completa.
Ela é indispensável quando a ordem original já representa:
Uma ordenação estável permite construir prioridades em etapas.
Considere:
Ana Vendas 5200 Carlos Suporte 4300 Beatriz Vendas 6100 Daniel Suporte 4800 Eduardo Vendas 4800
Primeiro, ordene pelo salário:
$ sort -s -k3,3n funcionarios.txt > etapa1.txt
Depois, ordene pelo departamento:
$ sort -s -k2,2 etapa1.txt
Como a segunda ordenação é estável, a ordem salarial é preservada dentro de cada departamento.
O mesmo resultado pode ser obtido em uma única execução:
$ sort \
-k2,2 \
-k3,3n \
funcionarios.txt
A abordagem em múltiplas passagens pode ser útil quando:
O GNU sort oferece duas comparações numéricas importantes.
A opção -n:
$ sort -n valores.txt
é apropriada para números comuns:
-12.5 0 3.14 150 2000
A opção -g, de *general numeric sort*:
$ sort -g valores.txt
reconhece uma variedade maior de representações, como:
1e6 2.7e-3 NaN -inf inf
Exemplo:
$ printf '%s\n' \
1e3 \
25 \
3.5e2 \
0.004 |
LC_ALL=C sort -g
Resultado:
0.004 25 3.5e2 1e3
Use -n para números decimais comuns. Use -g quando houver notação científica, infinitos ou representações especiais.
A opção -h interpreta sufixos de magnitude:
$ sort -h
Ela reconhece valores como:
900K 4M 1.5G 2T
Um uso comum:
$ du -h --max-depth=1 |
sort -hr
Para evitar problemas provocados por nomes com espaços, podemos fazer com que du coloque o tamanho em uma chave separada por tabulação, como já ocorre normalmente, e limitar a ordenação ao primeiro campo:
$ du -h --max-depth=1 |
sort -t$'\t' -k1,1hr
Nesse caso:
-k1,1hr
significa:
Isso evita que o nome do caminho participe do desempate desejado. Se dois tamanhos forem iguais e quisermos preservar a ordem original:
$ du -h --max-depth=1 |
sort -s -t$'\t' -k1,1hr
Uma comparação textual não compreende a estrutura de versões:
aplicacao-1.9 aplicacao-1.10 aplicacao-1.11 aplicacao-1.2
Use:
$ sort -V versoes.txt
Resultado:
aplicacao-1.2 aplicacao-1.9 aplicacao-1.10 aplicacao-1.11
Isso também resolve a ordenação natural de nomes numerados:
$ printf '%s\n' \
capitulo20 \
capitulo3 \
capitulo100 \
capitulo10 |
sort -V
Resultado:
capitulo3 capitulo10 capitulo20 capitulo100
Podemos aplicar a comparação de versões a uma coluna:
$ sort -t';' -k2,2V pacotes.txt
Para mostrar as versões mais recentes primeiro:
$ sort -t';' -k2,2Vr pacotes.txt
A ordenação textual de endereços IP costuma produzir resultados incorretos:
192.168.1.100 192.168.1.20 10.0.0.8 10.0.0.15
Uma solução é tratar cada octeto como uma chave numérica:
$ sort -t. \
-k1,1n \
-k2,2n \
-k3,3n \
-k4,4n \
ips.txt
Resultado:
10.0.0.8 10.0.0.15 192.168.1.20 192.168.1.100
Se o endereço estiver na primeira coluna de um arquivo de log:
192.168.1.20 acesso-permitido 10.0.0.8 acesso-negado
a chave final precisa terminar antes do espaço. Uma solução robusta é transformar temporariamente os octetos em campos separados ou usar uma ferramenta como awk para gerar uma chave auxiliar.
Exemplo:
$ awk '
{
split($1, ip, ".")
printf "%03d.%03d.%03d.%03d\t%s\n",
ip[1], ip[2], ip[3], ip[4], $0
}' acessos.txt |
sort -k1,1 |
cut -f2-
A chave formatada:
010.000.000.008
é eliminada após a ordenação.
Esse padrão de gerar uma chave auxiliar é extremamente útil quando os dados não estão em um formato que o sort consiga interpretar diretamente.
Suponha que um arquivo contenha datas no formato brasileiro:
Ana;31/12/2025;1200 Carlos;05/01/2024;900 Beatriz;17/08/2025;1500
Podemos usar três chaves:
$ sort -t';' \
-k2.7,2.10n \
-k2.4,2.5n \
-k2.1,2.2n \
arquivo.txt
Porém, a expressão é difícil de manter. Outra abordagem é gerar uma chave ISO temporária:
$ awk -F';' '
{
split($2, data, "/")
printf "%04d-%02d-%02d\t%s\n",
data[3], data[2], data[1], $0
}' arquivo.txt |
sort -k1,1 |
cut -f2-
A técnica segue três etapas:
awk cria uma chave adequada;
sort ordena por essa chave;
cut remove a chave auxiliar.
Ela funciona para:
Suponha que os níveis de prioridade sejam:
crítica alta média baixa
Uma ordenação alfabética não produz essa sequência. Podemos criar uma chave numérica:
$ awk '
{
prioridade = $1
if (prioridade == "crítica")
ordem = 1
else if (prioridade == "alta")
ordem = 2
else if (prioridade == "média")
ordem = 3
else if (prioridade == "baixa")
ordem = 4
else
ordem = 99
printf "%02d\t%s\n", ordem, $0
}' tarefas.txt |
sort -k1,1n |
cut -f2-
Uma versão mais compacta:
awk '
BEGIN {
ordem["crítica"] = 1
ordem["alta"] = 2
ordem["média"] = 3
ordem["baixa"] = 4
}
{
valor = ($1 in ordem) ? ordem[$1] : 99
printf "%02d\t%s\n", valor, $0
}' tarefas.txt |
sort -k1,1n |
cut -f2-
A opção --debug mostra quais partes das linhas são utilizadas na comparação:
$ sort --debug -k2,2 arquivo.txt
Para uma chave numérica:
$ sort --debug -k3,3n funcionarios.txt
O comando sublinha as regiões reconhecidas como chaves e pode emitir avisos, como:
sort: text ordering performed using ‘pt_BR.UTF-8’ sorting rules
ou:
sort: key 1 is numeric and spans multiple fields
Use --debug quando:
O resultado contém marcações de diagnóstico. Portanto, não deve ser enviado diretamente para o arquivo final.
A opção -u mantém uma linha por grupo de chaves equivalentes.
Considere:
1001;Ana;ativo 1001;Ana;inativo 1002;Carlos;ativo 1002;Carlos;bloqueado
Execute:
$ sort -t';' -u -k1,1n registros.txt
O resultado terá apenas um registro para cada código:
1001;Ana;ativo 1002;Carlos;ativo
A eliminação não se baseou na igualdade das linhas completas. Ela se baseou apenas na chave:
-k1,1n
Isso permite selecionar um registro por identificador, mas surge uma pergunta importante: qual deles será preservado?
A resposta depende dos critérios de ordenação e da estabilidade. Se queremos preservar a primeira ocorrência:
$ sort -s -t';' -u -k1,1n registros.txt
A combinação -s -u impede que a linha completa seja usada como desempate e conserva a primeira linha de cada grupo equivalente na entrada ordenada.
Considere:
1001;2026-01-10;ativo 1002;2026-02-05;ativo 1001;2026-03-18;inativo 1002;2026-01-20;bloqueado
Queremos conservar o registro mais recente de cada código.
Primeiro, ordenamos pelo código e pela data decrescente:
$ sort -t';' \
-k1,1n \
-k2,2r \
registros.txt
Depois, mantemos somente o primeiro registro de cada código:
$ sort -t';' \
-k1,1n \
-k2,2r \
registros.txt |
sort -s -t';' -u -k1,1n
Entretanto, a segunda execução reorganiza os dados por código. Para selecionar explicitamente a primeira linha de cada grupo, awk torna a intenção mais clara:
$ sort -t';' \
-k1,1n \
-k2,2r \
registros.txt |
awk -F';' '!visto[$1]++'
Resultado:
1001;2026-03-18;inativo 1002;2026-02-05;ativo
Esse padrão combina bem as responsabilidades:
sort organiza os registros;
awk seleciona o primeiro de cada grupo.
Considere:
web;servidor01;38 db;servidor02;92 web;servidor03;75 db;servidor04;64 cache;servidor05;48
Queremos o maior valor de cada categoria.
Ordene pela categoria e pelo valor decrescente:
$ sort \
-t';' \
-k1,1 \
-k3,3nr \
servidores.txt |
awk -F';' '!visto[$1]++'
Resultado:
cache;servidor05;48 db;servidor02;92 web;servidor03;75
Para obter os três maiores valores de cada grupo:
$ sort \
-t';' \
-k1,1 \
-k3,3nr \
servidores.txt |
awk -F';' 'contador[$1]++ < 3'
Essa combinação é útil na análise de:
Quando vários arquivos já estão ordenados pelos mesmos critérios, não é necessário ordená-los novamente. Use -m:
$ sort -m arquivo1.txt arquivo2.txt arquivo3.txt
O comando intercala as linhas, mantendo a ordenação global.
Para eliminar chaves duplicadas:
$ sort -mu \
arquivo1.txt \
arquivo2.txt \
arquivo3.txt
Com chaves específicas:
$ sort -m \
-t';' \
-k1,1n \
parte1.csv \
parte2.csv \
parte3.csv
Antes, verifique cada entrada:
$ for arquivo in parte1.csv parte2.csv parte3.csv
do
if ! sort -C -t';' -k1,1n "$arquivo"
then
printf 'Arquivo fora de ordem: %s\n' "$arquivo" >&2
exit 1
fi
done
Depois:
$ sort -m \
-t';' \
-k1,1n \
parte1.csv \
parte2.csv \
parte3.csv \
-o consolidado.csv
A mesclagem possui custo menor do que uma nova ordenação completa, especialmente em arquivos muito grandes.
A opção -C verifica silenciosamente se a entrada está ordenada:
$ sort -C arquivo.txt
Seu valor está no código de saída:
$ if sort -C -t';' -k1,1n dados.csv
then
echo "Arquivo corretamente ordenado."
else
echo "Arquivo fora de ordem." >&2
exit 1
fi
A opção -c também verifica, mas apresenta a primeira desordem encontrada:
$ sort -c -t';' -k1,1n dados.csv
Essa validação é útil antes de:
sort -m;
join;
O comando join exige que os dois arquivos estejam ordenados pelos campos utilizados na junção.
Considere usuarios.txt:
1001 Ana 1002 Carlos 1003 Beatriz
E saldos.txt:
1003 950 1001 1200 1002 500
Prepare ambos com os mesmos critérios:
$ LC_ALL=C sort -k1,1 usuarios.txt > usuarios.ordenado $ LC_ALL=C sort -k1,1 saldos.txt > saldos.ordenado
Faça a junção:
$ LC_ALL=C join \
-1 1 \
-2 1 \
usuarios.ordenado \
saldos.ordenado
Resultado:
1001 Ana 1200 1002 Carlos 500 1003 Beatriz 950
É fundamental usar a mesma localidade no sort e no join. Caso contrário, os programas podem discordar sobre a ordem das chaves.
Linhas são normalmente separadas por \n. Isso representa um problema ao processar nomes de arquivos, pois um nome válido pode conter uma quebra de linha.
Use uma cadeia terminada por caractere nulo:
$ find . -type f -print0 |
sort -z
Para processar o resultado:
$ find . -type f -print0 |
sort -z |
while IFS= read -r -d '' arquivo
do
printf 'Arquivo: %q\n' "$arquivo"
done
Ou:
$ find . -type f -print0 |
sort -z |
xargs -0 -r comando
Para ordenar por tamanho, gere registros também terminados por NUL:
$ find . -type f -printf '%s\t%p\0' |
sort -z -t$'\t' -k1,1n
Para imprimir o resultado em linhas convencionais:
$ find . -type f -printf '%s\t%p\0' |
sort -z -t$'\t' -k1,1n |
tr '\0' '\n'
O último comando é apropriado para visualização. Se um nome contiver uma quebra de linha, sua representação visual ainda poderá ocupar mais de uma linha. Para continuar processando os dados com segurança, preserve o terminador NUL.
Um exemplo útil:
$ find /var/log \
-type f \
-printf '%s\t%p\0' 2>/dev/null |
sort -z -t$'\t' -k1,1nr |
head -z -n 20 |
while IFS=$'\t' read -r -d '' tamanho arquivo
do
printf '%12d %q\n' "$tamanho" "$arquivo"
done
O fluxo funciona assim:
find imprime tamanho e caminho, terminados por NUL;
sort -z preserva os registros com segurança;
head -z seleciona os vinte maiores;
printf %q exibe caracteres especiais de forma inequívoca.
A opção head -z faz parte do GNU Coreutils. Em outros sistemas Unix, pode não estar disponível.
Considere um log:
2026-08-25 10:31:15 servidor02 WARN Disco quase cheio 2026-08-25 09:12:03 servidor01 INFO Serviço iniciado 2026-08-24 23:58:44 servidor03 ERROR Falha de conexão
Como a data e a hora estão no formato ISO, podemos usar:
$ sort -k1,1 -k2,2 log.txt
Para apresentar as mensagens mais recentes primeiro:
$ sort -k1,1r -k2,2r log.txt
Podemos definir uma única chave abrangendo os dois campos:
$ sort -k1,2r log.txt
Nesse caso, a comparação utiliza desde o início do primeiro campo até o fim do segundo.
Para ordenar pelo servidor e depois pela data:
$ sort \
-k3,3 \
-k1,1 \
-k2,2 \
log.txt
A saída tradicional de:
$ ps aux
possui campos separados por quantidades variáveis de espaços, e o último campo pode conter espaços. Ainda é possível processá-la, mas é melhor pedir ao ps uma saída controlada.
Processos por memória:
$ ps -eo pid=,user=,rss=,comm= |
sort -k3,3nr |
head -20
Processos por CPU:
$ ps -eo pid=,user=,pcpu=,comm= |
LC_ALL=C sort -k3,3gr |
head -20
Use -g para lidar melhor com números decimais no campo %CPU.
Para mostrar memória em MiB, gere uma chave auxiliar:
$ ps -eo pid=,user=,rss=,comm= |
sort -k3,3nr |
awk '
BEGIN {
printf "%-8s %-15s %12s %s\n",
"PID", "USUÁRIO", "MEMÓRIA", "COMANDO"
}
{
printf "%-8s %-15s %9.1f MiB %s\n",
$1, $2, $3 / 1024, $4
}' |
head -21
A ordenação deve acontecer antes da conversão e da inclusão do cabeçalho.
Arquivos tabulares frequentemente possuem uma linha de cabeçalho.
Uma solução comum:
$ {
IFS= read -r cabecalho
printf '%s\n' "$cabecalho"
LC_ALL=C sort -t';' -k3,3nr
} < dados.csv > dados-ordenados.csv
Esse formato evita executar head e tail separadamente sobre o mesmo arquivo.
O bloco:
$ {
...
} < dados.csv
compartilha a entrada entre read e sort. A primeira operação consome o cabeçalho e sort recebe as linhas restantes.
Para substituir o arquivo com segurança:
$ temporario=$(mktemp)
{
IFS= read -r cabecalho
printf '%s\n' "$cabecalho"
LC_ALL=C sort -t';' -k3,3nr
} < dados.csv > "$temporario" &&
mv -- "$temporario" dados.csv
Em um script completo, também é recomendável remover o arquivo temporário em caso de interrupção:
$ temporario=$(mktemp) || exit 1
trap 'rm -f -- "$temporario"' EXIT HUP INT TERM
{
IFS= read -r cabecalho
printf '%s\n' "$cabecalho"
LC_ALL=C sort -t';' -k3,3nr
} < dados.csv > "$temporario" || exit 1
mv -- "$temporario" dados.csv
trap - EXIT
O sort divide entradas extensas em blocos, grava resultados intermediários e depois os mescla.
As opções mais relevantes são:
-S -T --parallel --compress-program
$ sort -S 2G arquivo-grande.txt
Ou como percentual da memória:
$ sort -S 40% arquivo-grande.txt
Reservar mais memória pode reduzir operações temporárias em disco, mas um valor exagerado pode pressionar o sistema e provocar uso de swap.
$ sort \
-T /dados/tmp \
arquivo-grande.txt
Podemos informar -T mais de uma vez:
$ sort \
-T /disco1/tmp \
-T /disco2/tmp \
arquivo-grande.txt
Isso pode distribuir arquivos temporários por sistemas de arquivos diferentes.
$ sort \
--parallel=8 \
arquivo-grande.txt
Mais processos não garantem desempenho proporcional. O gargalo pode estar:
$ sort \
--compress-program=gzip \
arquivo-grande.txt
A compressão troca uso de armazenamento e entrada/saída por consumo de CPU. Em discos lentos e dados altamente compactáveis, ela pode trazer ganhos. Em SSDs rápidos ou processadores ocupados, pode piorar o desempenho.
Um exemplo:
$ LC_ALL=C sort \
--parallel=8 \
-S 40% \
-T /dados/sort-tmp \
-t$'\t' \
-k1,1 \
-k2,2n \
entrada.tsv \
-o saida.tsv
Antes de executar, verifique espaço:
$ df -h /dados/sort-tmp
Confira os inodes:
$ df -i /dados/sort-tmp
Em uma ordenação externa, o espaço temporário necessário pode ser significativo. Não use um diretório localizado em uma partição quase cheia.
Podemos medir diferentes configurações:
$ time LC_ALL=pt_BR.UTF-8 \
sort arquivo-grande.txt \
-o /dev/null
Compare com:
$ time LC_ALL=C \
sort arquivo-grande.txt \
-o /dev/null
Depois:
$ time LC_ALL=C \
sort \
--parallel=4 \
-S 1G \
arquivo-grande.txt \
-o /dev/null
Para evitar conclusões precipitadas:
Uma configuração mais rápida que produz uma ordem linguística diferente não é necessariamente uma substituição válida.
Considere:
$ sort -n -k2,2 -k3,3 arquivo.txt
A opção global -n pode afetar todas as chaves que não possuam um modificador específico.
Se o segundo campo for textual e o terceiro numérico, prefira:
$ sort \
-k2,2 \
-k3,3n \
arquivo.txt
Associar o modificador à chave reduz ambiguidades e torna a intenção evidente para quem mantiver o script.
O mesmo vale para:
b d f g h M n R r V
Exemplo:
$ sort \
-k1,1f \
-k2,2Vr \
arquivo.txt
A primeira chave ignora diferenças entre maiúsculas e minúsculas. A segunda interpreta versões em ordem inversa.
Considere:
1001;Ana;5200 1002;;4800 1003;Carlos; 1004;Beatriz;6100
O delimitador é:
$ -t';'
Campos vazios continuam existindo. Para ordenar pelo segundo campo:
$ sort -t';' -k2,2 arquivo.txt
O registro com campo vazio normalmente aparecerá antes dos nomes.
Para colocar campos vazios ao final, podemos gerar uma chave auxiliar:
$ awk -F';' '
{
vazio = ($2 == "") ? 1 : 0
printf "%d\t%s\t%s\n", vazio, $2, $0
}' arquivo.txt |
sort -t$'\t' -k1,1n -k2,2 |
cut -f3-
A primeira chave separa registros preenchidos dos vazios. A segunda organiza os valores existentes.
O uso de:
$ sort -t, -k3,3 arquivo.csv
só é confiável em arquivos simples, nos quais vírgulas não aparecem dentro dos campos.
Este registro possui uma vírgula interna:
1001,"Almeida, Ana",5200
Para o sort, ele possui quatro campos:
1001 "Almeida Ana" 5200
Isso não corresponde à estrutura lógica do CSV.
Para CSVs reais, use ferramentas que compreendam:
Uma solução consiste em converter o CSV para um formato intermediário seguro, ordenar e depois reconstruí-lo com uma biblioteca apropriada.
O script abaixo preserva o cabeçalho, ordena um arquivo separado por ponto e vírgula e grava o resultado com segurança:
$ #!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
if (( $# != 2 ))
then
printf 'Uso: %s ARQUIVO_ENTRADA ARQUIVO_SAÍDA\n' \
"${0##*/}" >&2
exit 2
fi
entrada=$1
saida=$2
if [[ ! -r $entrada ]]
then
printf 'Não foi possível ler: %s\n' "$entrada" >&2
exit 1
fi
diretorio_saida=${saida%/*}
if [[ $diretorio_saida == "$saida" ]]
then
diretorio_saida=.
fi
temporario=$(mktemp \
"$diretorio_saida/.sort.XXXXXX")
trap 'rm -f -- "$temporario"' EXIT HUP INT TERM
{
IFS= read -r cabecalho
printf '%s\n' "$cabecalho"
LC_ALL=C sort \
-s \
-t';' \
-k2,2f \
-k3,3nr
} < "$entrada" > "$temporario"
mv -- "$temporario" "$saida"
trap - EXIT
O script:
$ sort -s -k1,1 arquivo |
awk '!visto[$1]++'
$ sort \
-k1,1 \
-k2,2nr \
arquivo |
awk '!visto[$1]++'
$ LC_ALL=C sort arquivo |
uniq -c |
sort -k1,1nr |
head -10
Supondo pacote versão:
$ sort \
-k1,1 \
-k2,2Vr \
pacotes.txt |
awk '!visto[$1]++'
$ LC_ALL=C sort \
-m \
-u \
arquivo1 \
arquivo2 \
arquivo3
$ if ! LC_ALL=C sort -C -k1,1 arquivo
then
echo "Entrada fora de ordem." >&2
exit 1
fi
### Nomes de arquivos em ordem segura
$ find . -type f -print0 |
LC_ALL=C sort -z |
xargs -0 -r comando
| Opção | Aplicação avançada |
|---|---|
-k |
Define chaves por campo e posição |
-t |
Define um delimitador de um caractere |
-s |
Impede desempate pela linha completa |
-u |
Mantém uma linha por chave equivalente |
-m |
Mescla entradas previamente ordenadas |
-C |
Valida silenciosamente a ordenação |
-c |
Informa o primeiro ponto fora de ordem |
-z |
Usa NUL como terminador de registro |
-V |
Compara números de versões |
-h |
Compara tamanhos com sufixos |
-g |
Reconhece representações numéricas gerais |
-S |
Controla aproximadamente o buffer |
-T |
Escolhe diretórios temporários |
--parallel |
Controla o paralelismo |
--compress-program |
Comprime arquivos temporários |
--debug |
Mostra a interpretação das chaves |
-o |
Grava diretamente no arquivo indicado |
O uso avançado de sort depende menos da memorização de opções e mais da compreensão de quatro conceitos: chaves, localidade, estabilidade e formato dos registros.
Uma chave bem delimitada:
$ sort -k2,2
é diferente de:
$ sort -k2
A ordenação estável:
$ sort -s
preserva a sequência de registros com chaves equivalentes. A opção -u elimina registros segundo as chaves de comparação, e não necessariamente segundo a linha completa. A definição:
$ LC_ALL=C
torna resultados técnicos mais previsíveis, enquanto -z permite processar nomes de arquivos sem depender da quebra de linha como separador.
Quando o formato original não oferece uma chave apropriada, a solução mais flexível é criar uma chave auxiliar:
$ gerar_chave |
sort |
remover_chave
Esse padrão permite ordenar datas, endereços IP, prioridades personalizadas e praticamente qualquer estrutura que possa ser transformada em uma representação comparável. É nesse ponto que sort deixa de ser apenas um organizador de linhas e passa a funcionar como uma peça central no processamento de dados com shell.