você está aqui: Home  → Arquivo de Mensagens

O comando sort e seus muitos recursos

Colaboração: Rubens Queiroz de Almeida

Data de Publicação: 22 de janeiro de 2018

É complicado afirmar isto, mas eu não consigo pensar em outro comando que seja tão utilizado quanto o sort (ordenação). Eu já escrevi dezenas de scripts usando este comando, sempre, é claro, em combinação com outros comandos.

Vejamos então alguns exemplos de aplicação. O comando sort, na sua forma mais simples, serve para ordenar o conteúdo de um arquivo. Tomemos o arquivo arq1.txt, que possui o seguinte conteúdo:

$ cat arq1.txt
x
a
h
j
k

O comando abaixo, executado sobre o arquivo arq1.txt, gerará o seguinte resultado:

$ sort arq1.txt
a
h
j
k
x

Podemos também ordenar o conteúdo de um arquivo de forma reversa, para isto basta fornecer a diretiva -r:

$ sort -r arq1.txt
x
k
j
h
a

Outro recurso muito útil é a combinação do conteúdo de dois arquivos. Neste caso, o conteúdo dos dois arquivos precisará estar ordenado previamente conforme nossa necessidade.

$ cat arq2.txt
aa
yy

$ cat arq3.txt
bb
zz

$ sort -m arq2.txt arq3.txt
aa
bb
yy
zz

A saída do comando sort, em todos os exemplos apresentados, tem sido redirecionada para a tela. Caso queiramos redirecionar esta saída para um arquivo para processamento posterior, temos duas opções equivalentes:

$ sort arq1.txt arq2.txt > arq1_arq2.txt 

ou

$ sort arq1.txt arq2.txt -o arq1_arq2.txt 

Como a Dicas-L tem mais de 20.000 assinantes, com bastante frequência eu preciso realizar alguma manutenção para remover endereços, classificar os assinantes por domínio, dentre outras coisas.

Como nós todos sabemos, o endereço <Queiroz (a) Dicas-L com BR> é exatamente igual a <queiroz (a) dicas-l com br>. Para endereços eletrônicos, a caixa (maiúsculas ou minúsculas) com a qual o email é escrito, não faz absolutamente nenhuma diferença. Por esta razão, qualquer operação realizada na minha lista de assinantes, tem que considerar os endereços independentemente da caixa.

Para ordenar um arquivo independentemente da caixa, usamos a diretiva -f ou --ignore-case.

$ cat lista.txt
sonia@acme.com.br
Rubens@acme.com.br
MARIA@ACME.COM.BR
mAria@acme.com.br
RUBENS@ACME.COM.BR

$ sort -f -u lista.txt
mAria@acme.com.br
Rubens@acme.com.br
sonia@acme.com.br

Como vimos, endereços de email que diferem apenas pela caixa, são exatamente iguais. Acrescentando a diretiva -u, que significa unique ou único, eliminamos as duplicatas, independentemente da forma como foram escritas. Esta alternativa é muito útil quando precisamos combinar diferentes arquivos de endereços eletrônicos para criar uma lista única e para evitar que uma mesma pessoa receba mais de uma mensagem. Muita gente fica bastante chateada quando recebe a mesma informação mais de uma vez.

Continuando, vamos usar o comando sort em conjunto com outros comandos, para localizar os arquivos do sistemas que estão ocupando mais espaço. Isto pode ser feito de várias maneiras, uma delas é com o comando find:

$ find . -size +1024k -print 

Este comando faz uma busca, a partir do diretório corrente, por arquivos que possuam um tamanho superior a 1024k ou 1MB.

É possível também associar a saída do comando find ao comando ls para sabermos exatamente o tamanho dos arquivos encontrados:

$ find . -size +100M | xargs ls -l
-rw------- 1 queiroz queiroz 122M Jun 11 22:53 ./.com.google.Chrome.nYb6u2
-rw-r--r-- 1 queiroz queiroz 133M Out 24 21:30 512x288-video-Dailymotion.mp4
-rw-r--r-- 1 queiroz queiroz 1,6G Set  3 14:09 linuxmint-18.2-cinnamon-64bit.iso
-rw-r--r-- 1 queiroz queiroz 123M Mar  2  2017 Universal_Studios,_Fev_2017.zip
-rw-r--r-- 1 queiroz queiroz 230M Set  6 22:02 WebinarJam_Webinar.mp

Como queremos identificar os maiores arquivos, o mais conveniente é ordenar o resultado em ordem reversa, dos maiores arquivos para os menores:

$ find . -size +100M | xargs ls -lh | sort -k5 -hr  
-rw-r--r-- 1 queiroz queiroz 1,6G Set  3 14:09 ./linuxmint-18.2-cinnamon-64bit.iso
-rw-r--r-- 1 queiroz queiroz 230M Set  6 22:02 ./WebinarJam_Webinar.mp4
-rw-r--r-- 1 queiroz queiroz 133M Out 24 21:30 ./512x288-video-Dailymotion.mp4
-rw-r--r-- 1 queiroz queiroz 123M Mar  2  2017 ./Universal_Studios,_Fev_2017.zip
-rw------- 1 queiroz queiroz 122M Jun 11 22:53 ./.com.google.Chrome.nYb6u2

Como de hábito, podemos fazer esta mesma pesquisa de uma outra forma:

$ find . -size +100M -exec ls -lh {} + | sort -k5 -hr

O exec terminado com + (que ninguém conhece) é centenas de vezes mais rápido que o exec com ;.. Veja o teste onde pesquiso no meu diretório todos os arquivos que usam o comando date:

$ time find . -type f -exec grep -l date {} \; > /dev/null 2>&1 
real    0m3.653s
user    0m0.052s
sys     0m0.228s

$ time find . -type f -exec grep -l date {} + > /dev/null 2>&1 
real    0m0.023s
user    0m0.012s
sys     0m0.004s

O comando sort ordenará a saída numericamente (-n) tomando por base o valor do quinto campo (a contagem começa em 1, que é o default) e reverter o resultado (-hr), colocando os maiores valores na frente.

A diretiva -h usada tanto no comando ls quanto no comando sort significa human readable format, ou seja, um formato que é apropriado para compreensão de seres humanos. Caso não especificassemos esta diretiva, teríamos um número em bytes e para ter a dimensão exata do seu significado (kbytes, megabytes ou gigabytes), precisaríamos fazer algumas continhas. Você pode ver que os valores estão ordenados numericamente e de forma correta, mesmo quando os valores contém letras.

Para ficar ainda melhor podemos fazer uma listagem contendo apenas o nome do arquivo e seu tamanho:

$ find . -size +100M -printf "%s\t%p\n" | sort -nr
1,6G ./linuxmint-18.2-cinnamon-64bit.iso
230M ./WebinarJam_Webinar.mp4
133M ./512x288-video-Dailymotion.mp4
123M ./Universal_Studios,_Fev_2017.zip
122M ./.com.google.Chrome.nYb6u2

onde:

%s Tamanho do arquivo em bytes
\t <TAB>
%p Caminho relativo do arquivo (se fosse %f, o nome do diretório seria removido)
\n <ENTER>

Para encerrar, coloque a linha acima em uma shell script, chamada, por exemplo, de findbig.sh de forma a tornar mais fácil o seu uso.

Mas como no Shell tudo tem diversas formas de fazer, sendo cada uma mais simples que a outra, sugiro que você simplesmente crie um apelido para esta linha fazendo:

$ alias grandoes='find . -size +100M -printf "%s\t%p\n" | sort -nr' 

Nesta sessão, toda vez que você escrever grandoes no prompt terá esta lista. Mas se você quiser que esse apelido sirva para qualquer sessão, basta colocar essa linha em um arquivo que é carregado durante o seu login como p.ex. o ~/.bashrc. Essa é a magia e a simplicidade do Shell.

Todos os comandos acima foram testados em um sistema LinuxMint 18.1. Para outros sistemas podem ocorrer ligeiras variações na sintaxe dos comandos e no ordenamento dos campos do comando ls que requeiram algumas alterações.

Para encerrar, vejamos em mais detalhes o recurso de ordenação segundo um dos campos de um arquivo.

$ cat arquivo1.txt
1:2:3:4:5:6
1:1:3:4:5:6
1:4:3:4:5:6
1:2:3:4:5:6
1:0:3:4:5:6
1:2:3:4:5:6
1:7:3:4:5:6
1:2:3:4:5:6
1:0:3:4:5:6
1:9:3:4:5:6

Como podemos ver, cada registro deste arquivo possui 6 campos delimitados pelo caractere :.

O comando

$ sort -t: -k2 -n arquivo1.txt 

gerará a seguinte saída

  |
  v
1:0:3:4:5:6
1:0:3:4:5:6
1:1:3:4:5:6
1:2:3:4:5:6
1:2:3:4:5:6
1:2:3:4:5:6
1:2:3:4:5:6
1:4:3:4:5:6
1:7:3:4:5:6

Observe que o segundo campo (diretiva -k2) , indicado pela seta, está ordenado numericamente em ordem crescente. Os campos deste arquivo são separados por :. O tipo de separador é indicado pela diretiva -t:. Em seguida à diretiva -t poderíamos indicar qualquer tipo de separador. O campo a ser ordenado é indicado pela diretiva -k2 (a contagem dos campos começa em 1).

A ordenação também pode ser feita numericamente, do maior para o menor valor:

$ sort -t: -k2 -nr arquivo1.txt 
  |
  v
1:9:3:4:5:6
1:7:3:4:5:6
1:4:3:4:5:6
1:2:3:4:5:6
1:2:3:4:5:6
1:2:3:4:5:6
1:2:3:4:5:6
1:1:3:4:5:6
1:0:3:4:5:6
1:0:3:4:5:6

Para encerrar, um uso interessante do comando sort. Vamos determinar quais são os comandos que você mais usa em seu sistema GNU/Linux. O registro dos comandos emitidos fica armazenado no arquivo .bash_history. Vamos lá:

$ sort .bash_history | uniq -c | sort -nr | head
341 ls
70 cd
29 ssh ii
29 ls -l
24 cd Downloads
20 vi a.t2t
16 ls -lt | head
16 cd ..
15 ls -lt
13 vi A
13 detox -s utf_8 *

O comando uniq remove as duplicidades e coloca um contador do número de ocorrências (diretiva -c). O comando sort com a diretiva -nr faz uma ordenação numérica (-n) reversa (-r) e são listadas apenas as dez primeiras ocorrências (comando head).

Estes são, na minha opinião, os recursos mais utilizados do comando sort, mas o comando é muito mais poderoso. Para saber mais, consulte a documentação do programa (man sort).



Veja a relação completa dos artigos de Rubens Queiroz de Almeida

 

 

Opinião dos Leitores

Gustavo Chaves
22 Jan 2018, 11:49
Muito bom!

Achei interessantíssimo o "find -exec {} +" que eu não conhecia. Também não costumo usar o -printf do find, mas preciso lembrar mais dele antes de sair usando o xargs pra qualquer coisa.

E eu não sabia que o sort tinha uma opção -h. Fantástico!

*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script