Shell Bash

Você o ama, ou ainda não o conhece!

Nós interagimos com os computadores de muitas maneiras, como através de teclado e mouse, por interfaces de tela sensível ao toque ou usando sistemas de reconhecimento de fala. E a maneira mais usada de interagir com computadores pessoais é chamada interface gráfica do usuário. Com uma interface gráfica, damos instruções mexendo e clicando com o mouse na tela para selecionar itens e agir sobre eles com ajuda de menus. Isso é possível porque o sistema operacional do computador disponibiliza uma interface gráfica que nos mostra representações visuais dos programas e dados em vez de texto.

Todos os sistemas operacionais modernas disponibilizam desta categoria de interface. É muito mais fácil para nos, usuários, visualizar as coisas desta forma, e informar através de gestos para o sistema o que deve fazer. Assim, a interface gráfica é bem um tipo de intérprete entre o usuário e o sistema operacional. Ela facilita as coisas para nós, isso é muito bom! Mas isso não as torna mais eficazes. De fato, essa interface não nos deixa mais funcionalidades do que quem o disponibilizou para nós, pensou. Eu sei que tem umas gambiarras por aí, mas mesmo assim as possibilidades são limitadas. Também, essas interfaces consomem muitos recursos da nossa máquina, principalmente a nossa preciosa memória RAM. Se você já fuçou um pouco nas coisas, você já sabe que esses recursos nem sempre estão disponíveis ou acessíveis, como é o caso quando queremos mexer em uma máquina de forma remota. Quando dominamos a interpretação das informações que procuramos ou a ação que queremos completar, é muitas vezes mais eficaz de passar as instruções para o sistema de uma forma um pouco mais direta. Aí você deve estar se perguntando, esse meio existe? A resposta é siim, é o shell!

Shell, o que é?

Um shell (concha ou casca, em português), é uma interface pela qual o usuário interage com o sistema operacional (é chamado shell porque é a camada mais externa envolvendo o núcleo/kernel do sistema operacional), seja esta interação por uma interface gráfica (Graphical User Interface - GUI) ou por meio de linha de comando (Command-Line Interface - CLI). Não obstante, no nosso dia dia, o shell é mais entendido como o interpretador que recebe comandos em formato de texto simples e chama os serviços do sistema operacional para fazer algo, aquele que você acessa pelo console ou terminal da sua máquina. Nesta categoria existem vários interpretadores de shell, mas aqui como indicado no título, trataremos do shell tipo Unix mais popular que é o Bash (acrônimo para Bourne Again SHell — assim chamado porque é derivado de um shell escrito por Stephen Bourne), lançado pela primeira vez em 1989. Bash é o interpretador shell padrão na maioria das implementações modernas do Unix e na maioria dos pacotes que fornecem ferramentas semelhantes ao Unix para Windows.

Observe que um terminal e um console podem ser confundidos funcionalmente, ambos oferecem a execução de uma sessão de shell. E, desse ponto de vista, não podemos fazer nada a mais ou a menos se estamos em um console comparando com um terminal. Na prática, o console é o equipamento físico de um terminal sem modo gráfico. Um terminal hoje em dia assume a forma de um aplicativo em janela em um ambiente gráfico para emular um console…mais sobre isso aqui

Historicamente, os primeiros sistemas operacionais não tinham interface gráfica igual que conhecemos hoje em dia. Aliás, na época, o mouse nem existia ainda. As interações com o sistema operacional era essencialmente por texto (mas sem emojis rs). A tela servia para receber as informações fornecidas pelo sistema em forma de frase, exibição de valor ou tabela textual. E o usuário utilizava o teclado para informar os comandos desejados ao sistema. É esta interface de troca textual chamada de shell.

O Shell do tipo Unix existe há mais tempo do que a maioria de seus usuários. Ele sobreviveu porque é uma ferramenta poderosa que permite aos usuários executar tarefas complexas e poderosas, geralmente com apenas algumas teclas ou linhas de código. Ele ajuda os usuários a automatizar tarefas repetitivas e combinar facilmente tarefas menores em fluxos de trabalho maiores e mais poderosos.

Enquanto uma GUI apresenta opções para selecionar, as opções da CLI não são apresentadas automaticamente a você, portanto, você terá que aprender alguns comandos, como novo vocabulário em um idioma que está estudando. No entanto, ao contrário de uma linguagem falada, um pequeno número de “palavras” (ou seja, comandos) leva você a um longo caminho. A gramática do shell permite combinar ferramentas existentes em pipelines poderosos e lidar com grandes volumes de dados automaticamente. As sequências de comandos podem ser gravadas em um script, melhorando a reprodutibilidade dos fluxos de trabalho.

Além disso, a linha de comando geralmente é a maneira mais fácil de interagir com máquinas e supercomputadores remotos (ex: usando um ssh, Secure shell). A familiaridade com o shell é quase essencial para executar uma variedade de ferramentas e recursos especializados, incluindo sistemas de computação de alto desempenho ou supercomputadores. À medida que clusters e sistemas de computação em nuvem se tornam mais populares para processamento de dados científicos, conseguir interagir com o shell está se tornando uma habilidade necessária.

Resumindo, o shell é uma interface pela qual o usuário interage com o computador. Partindo de um ponto de vista funcional, ele cumpre a mesma função da interface gráfica de um sistema Windows, Linux, ou MacOS. Mas como iremos ver nesta pequena demonstração, apesar do fato dele seja “menos refinado” visualmente, o seu poder é quase infinito!

Sujando as mãos

Imagina que para uma pesquisa você tenha recebido os arquivos de coleta de 5 espécies de plantas contendo em cada linha o nome da espécie, a sua altura medida em campo e a sua coordenada de localização x e y. A nossa expectativa é sempre receber ou encontrar aqueles arquivos .xls, .txt ou .csv com tudo bonitinho ali para partir para análise, e geralmente chega a surpresa rs (para falar verdade, eu fico surpreso é quando acontece o contrário rs). Ao descompactar a pasta você se depara com 10 sub-pastas cada uma contendo vários arquivos (.txt e .seila) e para piorar você abriu um deles e “tandanm”! a galera que realizou a coleta resolveu facilitar a sua vida em misturar as espécies. Resumindo, você tem centenas de arquivos distribuídos em pastas diferentes onde as observações sobre as 5 espécies vêm tudo misturadas. Após reclamar e comentar essa maldade com a primeira vítima pessoa que você encontrou, alguém tem que arrumar essa bagunça…infelizmente é você. Vamos supor que você vai querer ter na sua pasta 5 arquivos, um por espécie, e também quer somente as 20 mais altas/baixas de cada uma (não vou complicar mais, chega). Usando a sua interface gráfica, você não apenas estaria clicando em sua mesa por várias horas, mas também arriscaria cometer algum erro no processo de concluir essa tarefa chata repetitiva. É aqui que aproveitamos do shell bash (daqui para frente usarei Shell e Bash como sinônimos). O shell é tanto uma interface de linha de comando quanto uma linguagem de script, permitindo que essas tarefas repetitivas sejam feitas de forma automática e rápida. Com os comandos adequados, o shell pode repetir tarefas com ou sem alguma modificação quantas vezes quisermos. Para este exemplo aqui apresentado, usando o shell, podemos realizar esta tarefa em menos de um segundo. Como?! Fique aqui que eu te mostro…e sim, tenho esses arquivos para a gente brincar aqui.

Nosso “hello word!”

Photo by Jukan Tateisi on Unsplash
Só para não burlar a regra, como de costume o primeiro passo que a gente dá com uma linguagem é imprimir na tela essa frase, então vamos lá, o comando que faz essa tarefa é echo ele printa na tela o que você passa para ele como argumento!

1
echo Olá mundo!
>>> Olá mundo!

As linhas que começam com esses “>>>” representam a saída do meu terminal.

A ajuda/documentação dos comandos pode ser acessada pelo terminal mesmo, digitando o_comando + --help (ex: echo --help) ou caso queira mais detalhes pode a acessar o manual deles sem sair do shell com man (ex: man echo)

Onde estamos?

O comando pwd “print working directory” nos mostra a pasta onde estamos.

1
pwd
>>> /home/tredgi/bash_test

Como pode ver na saída acima, estou na pasta bash_test cujo caminho completo é /home/tredgi/bash_test.

O comando ls

Estando dentro de uma pasta, o comando ls lista o conteúdo da pasta.

1
ls
>>> pasta_001
>>> pasta_002
>>> pasta_003
>>> pasta_004
>>> pasta_005
>>> pasta_006
>>> pasta_007
>>> pasta_008
>>> pasta_009
>>> pasta_010

Pode ver que aqui temos 10 pastas com nomes não muito criativos, começando em pasta_001 até pasta_010, voltaremos a eles depois.

Criação de nova pasta

1
2
mkdir nova_pasta
ls
>>> nova_pasta
>>> pasta_001
>>> pasta_002
>>> pasta_003
>>> pasta_004
>>> pasta_005
>>> pasta_006
>>> pasta_007
>>> pasta_008
>>> pasta_009
>>> pasta_010

Para isso utilizamos o comando mkdir seguido do nome que queremos (pode ser um ou vários, é só separá-los com espaço vazio) e em seguido foi utilizado o comando ls para listar tudo que tem na nossa pasta, e como esperado, agora temos uma pasta a mais.

Vamos entrar nesta nova pasta. Para isso temos que utilizar o comando cd de “Change Directory” para mudar de pasta, passando o nome/caminho da pasta como argumento para ele.

1
2
cd nova_pasta
pwd
>>> /home/tredgi/bash_test/nova_pasta

Já estamos dentro, podemos criar um arquivo vazio dentro dela, utilizando o comando touch seguido do nome do arquivo.

1
2
touch novo_arquivo.txt
ls
>>> novo_arquivo.txt

Podemos escrever coisas dentro dele, lembra que echo printava na nossa tela o que passávamos para ela? Pois, bem! Podemos pegar este conteúdo e redirecionar para o nosso arquivo vazio com o comando >.

1
echo Olá mundo, de novo! > novo_arquivo.txt

Podemos verificar o conteúdo deste nosso arquivo com o comando cat (de concatenar), chamando este comando seguido do nome do arquivo ele abre o conteúdo do arquivo no terminal mesmo. Para grandes que não cabem na tela, temos alternativos com head que mostra somente a cabeça as primeiras linhas do arquivo e tail que mostra as últimas linhas do arquivo. Ainda os comandos less e more nos dão a flexibilidade de navegar no arquivo. Para saber mais verifica as documentações com --help ou man sem mesmo sair do terminal. Aqui usarei o cat, pois o arquivo só tem uma linha.

1
cat novo_arquivo.txt
>>> Olá mundo, de novo!

E não é que tem a nossa frase lá?! Perfeito! Até aqui já exploramos umas coisas muito corriqueiras de fazer no shell.

Agora vamos dar um passinho para trás, voltar para a pasta bash_test e explorar mais coisas.

1
2
cd /home/tredgi/bash_test
ls
>>> nova_pasta
>>> pasta_001
>>> pasta_002
>>> pasta_003
>>> pasta_004
>>> pasta_005
>>> pasta_006
>>> pasta_007
>>> pasta_008
>>> pasta_009
>>> pasta_010

Isso você já sabia como fazer, usei o cd seguido de caminho desejado, depois listei os arquivos presentes. As nossas 11 pastas continuam aí.

Não precisamos mais da nova pasta, vamos deletar ele? Bora!

1
2
rm -r nova_pasta
ls
>>> pasta_001
>>> pasta_002
>>> pasta_003
>>> pasta_004
>>> pasta_005
>>> pasta_006
>>> pasta_007
>>> pasta_008
>>> pasta_009
>>> pasta_010

O comando rm remova um arquivo, mas a nossa pasta não estava vazia, para informar par o bash que queremos deletar a pasta inclusive o seu conteúdo novo_arquivo.txt que acabamos de criar, utilizamos a opção -r que é uma abreviação de --recursive (para ver todas as opções, roda rm --help no seu terminal).

Explorando aquelas pastas e seus conteúdos

Vamos entrar na pasta pasta_008

1
2
3
cd pasta_008
pwd
ls | head
>>> /home/tredgi/bash_test/pasta_008
>>> ADCQM1779T.txt
>>> ALCNY6474C.txt
>>> APJWO5882G.txt
>>> AXNIM7722H.txt
>>> BNTAZ6158W.seila
>>> BYXBG2428H.seila
>>> CEVDJ4108I.txt
>>> CGMGB8286K.txt
>>> CHWIE4251Z.txt
>>> DDJVB4228K.seila

Aqui chamei 3 comandos, o cd mudou o diretório em seguido o comando pwd printa na tela o caminho onde estamos atualmente e depois o comando ls para listar os arquivos que estão presentes dentro daquela pasta e por fim, não menos importante, o comando head que limita as linhas mostradas por ls pegando somente as primeiras observações. Note que entre ls e head tem um | ele é um operador chamado “pipe” (tubo, em português) permitindo que a saída do comando anterior passe dentro dele e serve como entrada do próximo comando, podemos encadear vários comando assim criando um pipeline.

Existem outros operadores permitindo executar sequencia de comandos no bash, eles são: ;, &, &&, e ||. Eles servem para propósitos diferentes, clique aqui para ter detalhes.

Podemos abrir o primeiro arquivo e ver o que tem dentro

Vamos pegar somente as primeiras observações utilizando o head, nem sabemos quantas linhas que o arquivo tem poderia ser qualquer um daqueles comandos que mencionei anteriormente.

1
head ADCQM1779T.txt
>>> especie;altura;x;y
>>> B;2.636;492588;9998812
>>> D;2.962;497264;9992606
>>> D;1.865;494560;9995394
>>> B;3.262;490926;9998056
>>> C;1.888;495076;9995726
>>> E;1.41;499154;9996568
>>> D;3.34;497916;9997742
>>> B;3.464;497258;9990826
>>> D;3.604;496684;9998156

hmmm são nossas tabelas, contendo 4 colunas: especie, altura, x e y. Você já deve estar se perguntando, quantas linhas têm esta tabela, quantas espécies distintas, quantos arquivos afinal, como arrumar isso?

Respondendo à sua primeira pergunta:

1
cat ADCQM1779T.txt | wc -l
>>> 94

Tem 94 linhas! Ainda bem que no comando anterior utilizamos o head para pegar somente as primeiras observações. Aqui foi utilizado o comando wc (word count) que conta quantas palavras e linhas tem um arquivo e com a opção -l ele retorna somente a quantidade de linhas. Lembra que cat mostra todas as linhas de um arquivo? Aqui ele foi útil, ao invés de printar o conteúdo na tela, a saída foi conduzido para wc poder contar via o “tubo” |, assim a única saída é a contagem de linhas.

Para responder as outras perguntas, vamos voltar de novo para a pasta bash_test com o comando cd

1
2
cd /home/tredgi/bash_test
pwd
>>> /home/tredgi/bash_test

Quantos arquivos têm cada pasta?

Primeiro vamos ver isso para uma pasta

1
ls pasta_003 | wc -l
>>> 72

Para caprichar, podemos até construir uma frase como resposta!

1
echo A pasta_003 tem $(ls pasta_003 | wc -l) arquivos!
>>> A pasta_003 tem 72 arquivos!

Aqui juntei umas coisinhas que já vimos até o momento. Mas você deve reparar que utilizei a estrutura $(algum_camando). Ela representa uma expressão de substituição de comando, executa tudo que está dentro dela, e nos dá somente a saída, assim quando echo está imprimindo as coisas que eu passei para ele exibir, ele não viu a expressão literalmente, mas a saída dela que é 72. A coisa interessante é que se conseguimos fazer isso para uma pasta, conseguimos fazer para todas, é só saber como pedir isso direitinho para bash. Você pensou em utilizar uma estrutura de repetição? Leu a minha mente rs…é isso mesmo que eu vou fazer para rodar para todas as 10 pastas.

Uma das estruturas de repetição for no bash é a seguinte:

for i in "alguma lista"; do
  "alguma ação sobre cada elemento da lista de entrada" $i
done

Note que i representa um elemento da nossa lista de entrada, sendo um em cada iteração da repetição. Note que quando chamei o i na repetição coloquei o $ na frente dele, lembra o que faz essa expressão? Substitua o i pela sua saída, i.e., um elemento a cada iteração.

Vamos voltar à nossa contagem

1
2
3
for i in $(ls); do 
  echo "A $i tem $(ls  $i | wc -l) arquivos"; 
done
>>> A pasta_001 tem 68 arquivos
>>> A pasta_002 tem 71 arquivos
>>> A pasta_003 tem 72 arquivos
>>> A pasta_004 tem 72 arquivos
>>> A pasta_005 tem 66 arquivos
>>> A pasta_006 tem 66 arquivos
>>> A pasta_007 tem 69 arquivos
>>> A pasta_008 tem 69 arquivos
>>> A pasta_009 tem 72 arquivos
>>> A pasta_010 tem 70 arquivos

Acredite se quiser, mas dá para calcular quantas linhas têm no total somando os arquivos por pasta!

1
2
3
for i in $(ls); do 
  echo "A $i tem $(ls  $i | wc -l) arquivos e somam $(cat $(find ./$i -mindepth 1) | wc -l) linhas"; 
done
>>> A pasta_001 tem 68 arquivos e somam 6201 linhas
>>> A pasta_002 tem 71 arquivos e somam 6490 linhas
>>> A pasta_003 tem 72 arquivos e somam 6569 linhas
>>> A pasta_004 tem 72 arquivos e somam 6535 linhas
>>> A pasta_005 tem 66 arquivos e somam 6015 linhas
>>> A pasta_006 tem 66 arquivos e somam 6011 linhas
>>> A pasta_007 tem 69 arquivos e somam 6250 linhas
>>> A pasta_008 tem 69 arquivos e somam 6305 linhas
>>> A pasta_009 tem 72 arquivos e somam 6550 linhas
>>> A pasta_010 tem 70 arquivos e somam 6355 linhas

Reaproveitei a mesma repetição for de antes e acrescentei o valor de linhas que tem os arquivos que contem cada pasta. Utilizei mais um comando para isso que é o find. Este comando tem um propósito parecido com ls, entretanto ele retorna o caminho do arquivo listado o que facilita ações sobre o arquivo, também a busca dele é recursiva, i.e., procura na pasta atual e também nas subjacentes, ainda se pode controlar a profundidade da busca com as opções -mindepth e -maxdepth.

Agora temos uma ideia melhor, sobre o que estamos lidando. Uma coisa é verdade, são muitos arquivos. Somente as duas primeiras pastas somam mais de 12 mil linhas de dados e não estou disposto a ficar contando enquanto o bash está sob os meus dedos. Pelo menos hoje não rs

Quantos arquivos no total?

1
find -mindepth 1 -type f | wc -l
>>> 695

Quantas linhas no total?

1
cat $(find -mindepth 1 -type f) | wc -l
>>> 63281

Voltando ao nosso problema

Não sei se você percebeu que quando eu entrei na pasta pasta_008 la em cima, não somente tenha arquivos .txt mas também temos arquivos com uma extensão estranha .seila (a minha criatividade para dar nomes foi lá pro alto rs). Mas o fato é, não poderemos utilizar esses arquivos, pois depois de uma conversa percebemos que foi obra de algum erro e que esses arquivos devem ser desconsideradas. Escutei você perguntando se vamos ter que clicar neles para excluir, não, cuidaremos disso de outra forma com bash mesmo.

Quantas espécies distintas

1
cat $(find . -name "*.txt") | cut -d ";" -f 1 | sort | uniq -d
>>> A
>>> B
>>> C
>>> D
>>> E
>>> especie

Como mostrado aqui nesta saída, temos 5 espécies de A até E. A partir daqui, estou trabalhando somente com os arquivos .txt, desconsiderando aqueles .seila. O Shell utiliza um recurso chamado Globbing para corresponder ou expandir tipos específicos de padrões, aqui o asterisco significa zero ou mais caracteres. Também temos novos comandos, utilizei o cat para ler todos os arquivos com extensão .txt que find encontrou depois o comando cut foi utilizado para recortar a parte da tabela que precisamos (informando que a delimitação da tabela é com ; e só queria a coluna 1, informei isso com a opção field=1), depois disso ordenei todos os valores que agora são somente as espécies representadas com uma letra em maiúscula com sort e por fim, uniq para pegar somente os valores únicos com a opção -d que pega somente um único valor nos grupos com duplicação de valores…uuuf, é isso rs

Globbing é usado principalmente para combinar nomes de arquivos ou pesquisar conteúdo em um arquivo usando caracteres curingas para criar o padrão.

Caracteres coringas comuns

  • * = Asterisco representa zero ou mais caracteres
  • ? = Representa um único caractere
  • [] = Representa uma série de caracteres.

Obs: globbing é um pouco diferente de expressões regulares.

Continuando…

Agora que sabemos quais espécies que temos medição de altura, podemos filtrar, ordenar elas pelo valor de altura, etc.

Filtrando as 20 observações mais altas da espécie D

1
cat $(find . -name "*.txt") | grep "^D" | sort -t ';' -k 2 -nr | head -n 20
>>> D;7.964;493778;9994640
>>> D;7.962;490326;9994312
>>> D;7.689;493792;9999286
>>> D;7.441;492332;9990466
>>> D;7.404;491638;9994490
>>> D;7.317;499420;9992064
>>> D;7.254;498228;9995980
>>> D;7.241;496974;9993794
>>> D;7.225;495070;9990952
>>> D;7.196;495338;9994106
>>> D;7.158;491800;9991420
>>> D;7.139;490222;9991432
>>> D;7.136;496076;9990434
>>> D;7.102;498890;9998394
>>> D;7.058;494112;9996256
>>> D;7.047;495642;9998192
>>> D;7.025;498606;9998246
>>> D;7.02;497390;9996960
>>> D;7.006;497288;9994394
>>> D;7.003;495030;9993962

Voilá, somente os valores mais altos da espécie D!

Aqui, utilizei outro recurso que é o grep para filtrar conteúdo nas linhas, informando que só quero as linhas que começam com “D”, i.e, observação da espécie “D”. Também chamei algumas opções com sort, -t para dizer que o separador é ;, -k para dizer que quero a coluna 2 “altura” e -nr para dizer que a ordenação deve ser numérica e de forma “reversa” decrescente…tem mais…depois vem o head com a opção -n dizendo que tem que captar 20 valores. Note que para encadear todos esses comandos, utilizei o pipe.

Alterando pouca coisa podemos reaproveitar esta linha para as outras espécies só trocando a letra. Mas bora ver para os valores mais baixos da espécie D.

1
cat $(find . -name "*.txt") | grep "^D" | sort -t ';' -k 2 -n | head -n 20
>>> D;0.3324;495742;9999820
>>> D;0.3519;499794;9992706
>>> D;0.5732;497556;9996130
>>> D;0.6255;496720;9991748
>>> D;0.6966;493554;9998012
>>> D;0.8018;498332;9999344
>>> D;0.8391;490976;9998010
>>> D;0.8616;498010;9994902
>>> D;0.8729;495106;9990540
>>> D;0.9557;493306;9993516
>>> D;1.014;498196;9991904
>>> D;1.048;491614;9996826
>>> D;1.053;499452;9992810
>>> D;1.063;491922;9991802
>>> D;1.071;496754;9998176
>>> D;1.103;496920;9994892
>>> D;1.11;498870;9991534
>>> D;1.121;499044;9997072
>>> D;1.132;496890;9990368
>>> D;1.143;498620;9996206

Para ter a ordem crescente, omiti a opção -r do comando sort.

Eu sei que estamos na linha de comando, mas nem por isso que não poderíamos deixar isso com mais cara de tabela mesmo. Para isso podemos utilizar o comando column.

1
cat $(find . -name "*.txt") | grep "^C" | sort -t ';' -k 2 -n | head -n 20 | column -s ';' -t
>>> C  0.1715  493524  9996398
>>> C  0.3115  498862  9993866
>>> C  0.3554  497694  9994088
>>> C  0.3627  495826  9990656
>>> C  0.3693  491098  9996290
>>> C  0.3824  492888  9996198
>>> C  0.3947  490470  9990560
>>> C  0.3965  499482  9992650
>>> C  0.4147  499162  9994490
>>> C  0.4388  497130  9991552
>>> C  0.458   492048  9994600
>>> C  0.4591  493212  9998618
>>> C  0.462   490020  9991736
>>> C  0.4966  495552  9998698
>>> C  0.5004  499584  9993488
>>> C  0.5224  496088  9995734
>>> C  0.5233  492438  9997520
>>> C  0.5309  491666  9992618
>>> C  0.5336  491748  9991110
>>> C  0.5561  495576  9998754

Percebeu que eu troquei de espécie? Também acho que column melhorou bem a representação visual rs

Salvar resultados em arquivos

Para ter esses resultados não precisamos ficar rodando toda hora, se bem que este é rápido, mas podemos jogar o que estamos vendo diretamente para um arquivo, somente o que realmente precisamos para a nossa análise. No exemplo abaixo vou salvar o nosso último resultado para um arquivo chamado menores_C.txt.

1
cat $(find . -name "*.txt") | grep "^C" | sort -t ';' -k 2 -n | head -n 20 > menores_C.txt

O que este comando faz?

  • Procurou em todas as 10 sub-pastas os arquivos com extensão .txt (630 em 695 arquivos);
  • Juntou todos os arquivos como se fosse uma única tabela (57360 linhas de dados);
  • Filtrou todas as linhas, retendo somente a espécie C (12699 linhas de dados);
  • Ordenou todas as linhas resultantes de acordo do valor de altura, em ordem crescente (12699 linhas de dados)
  • Selecionou somente as 20 primeiras observações que neste caso são as mais baixas;
  • Salvou essas 20 linhas resultantes no arquivo menores_C.txt

Uma última coisa, você deve estar se perguntando a respeito do tempo que esses comandos levam para realizar essa lista de tarefa. É pouco tempo! Mas “pouco tempo” é algo muito relativo. Bora ver quanto tempo no meu terminal!

Siim, você viu bem! Levou menos de 1 segundo, sendo mais específico, levou 73 milissegundos. Eu sei que talvez você levou uns trinta minutos até chegar nesta parte, pois eu precisei preparar o caminho…mas, é somente uma linha de código dizendo especificamente para o nosso interpretador shell que aqui é o bash, o que queremos fazer.


Conseguimos! \o/\o/\o/

Quando o bash interpreta/executa os comandos que o usuário digita no console, isso é chamado de modo interativo. Mas também pode processar uma lista de comandos pré-gravados em um arquivo, isso é chamado modo de script ou, mais geralmente, shell script. E se isso não bastasse, o shell inclui estruturas de programação que fornecem flexibilidade adicional aos scripts. Torna-se então uma linguagem de programação bastante completa…só imagina o quanto que você conseguiria fazer com o seu shell script tendo o bash alí para interpretar tudo que você quiser, incrível não é?!

Conclusão

Dominar o shell é, de certa forma, dominar UMA linguagem para se comunicar com o computador. Hoje em dia, onde todos os computadores conseguem oferecer uma interface gráfica, pode parecer arcaico usar um terminal. Na verdade, não é assim, porque a interação por uma linguagem textual oferece uma riqueza e uma flexibilidade ilimitada para descrever ações.

Para nos convencermos disso, podemos fazer a seguinte analogia com a linguagem humana: a interface gráfica equivale a um pequeno livro “guia do viajante”, que contém frases prontas para uma língua estrangeira. Mas conhecer a língua estrangeira continua a ser a forma mais eficaz de fazer frases adaptadas a todas as suas necessidades de comunicação, presentes e futuras, por isso mesmo as necessidades que não esperávamos inicialmente e que também não estão previstas na nossa pequena guia…

O shell nunca desapareceu, apenas se tornou cada vez menos visível para o grande público. Essencialmente porque para o público a ênfase foi colocada na facilidade de uso mais do que na eficácia e poder desse uso. Mas as coisas já começaram a mudar, à medida que mais e mais usuários querem ir mais longe, pois como você, são entusiastas que buscam controlar melhor seu computador. Também, em sistemas operacionais proprietários como o Windows desde na sua versão de Windows 10, passou a oferecer um acesso mais imediato ao shell por meio do WSL Subsistema do Windows para Linux principalmente.

Gostaria de deixar claro que, aqui não se trata de recomendar que você jogue o seu mouse no lixo e ficar fazendo tudo pela linha de comando. Mas de preferência, lhe apresentar o bash como uma ferramenta que em algumas situações vale a pena utilizar, como para automatizar tarefas repetitivas, poupando tempo e evitando erros que podem ocorrer no meio da realização manual dessas tarefas.

Espero que essa pequena demonstração tenha despertado o seu interesse sobre o que é o shell e o seu poder.

Até+!

Alguns links importantes de consulta! O Bash é um assunto bem amplo, esses links podem te servir de referências e te levar além.

Related