Introdução à Linha de Comando Linux

Julia Apolonio & João Cavalcante

Manipulando arquivos

Um pouco sobre mim…

Atividades de Pesquisa:

  • Mestranda em Bioinformática, UFRN
    • GWAS e desenvolvimento de software, orientada pela Dr. Vasiliki Lagou

Projetos em andamento:

O que é o Shell?

  • Tipicamente, quando interagimos com um computador, utilizamos graphical user interface (ou GUI), que funciona através de interações com o mouse.

  • É difícil fornecer instruções complexas para uma GUI, com muitos passos ou que envolvam várias operações sequenciais. Por exemplo, se você precisar copiar a terceira linha de mil arquivos de texto em centenas de diferentes diretórios.

  • Portanto, por fazerem tais atividades triviais, as interfaces de linha de comando (CLIs) são indispensáveis. Nesse contexto, temos o Shell, o programa onde o usuário digita comandos, que serão então executados e interpretados. O Shell mais popular hoje em dia, e presente em sistemas operacionais Unix, como o Linux, é o Bash.

Hello World!

Como todo curso de programação que se preze, vamos começar fazendo nosso ‘hello world’ em Shell:

echo 'Hello World!'

Comandos no shell

A maneira que interagimos com o shell é através de comandos digitados no prompt, que são então executados quando você pressiona a tecla Enter.

Mas você ainda não sabe nenhum comando! Então, para começarmos, use o comando ls, que significa listar, que lista os arquivos na pasta, ou diretório, atual:

ls

Diretório de trabalho

O prompt listou todos os arquivos e diretórios presentes onde você está. Mas onde você está agora? Com o comando ‘pwd’, que significa Print Working Directory, você consegue ver o caminho absoluto para onde o seu prompt está apontando:

pwd

Se você seguiu as instruções à risca até aqui, o output do prompt deve ser o seu ‘Home Directory’, ou seja, o local que você entra quando faz login. Cada usuário no computador tem o seu próprio, e ele deve ter um formato /home/<USUARIO>.

Movendo entre pastas

Agora, para se mover dentro do sistema de arquivos, você pode usar o comando ‘cd’, de change directory:

cd Downloads

Você entrou no diretório de downloads do seu computador. Você pode checar os arquivos existentes usando ‘ls’ e pode verificar onde está usando ‘pwd’.

ls
pwd

Opções do ls

Se você tem um grande número de arquivos no seu diretório, é complicado localizar algum arquivo apenas listando todos. Para isso, podemos usar alguns artifícios do comando ls:

ls -t #organiza por tempo em vez de ordem alfabética
ls -tr #reverte a ordem anterior (mostra o mais recente por último)
ls -s #mostra o tamanho de cada arquivo em blocos
ls -sh #mostra o tamanho de cada arquivo em formato de leitura humano
ls *.zip #mostra todos os arquivos que terminam com ".zip"
ls sh* #mostra todos os arquivos que começam com "sh"
ls *lesson* #mostra todos os arquivos que contém "lesson" em algum canto do nome

Dezipar arquivos

Agora que achamos o arquivo com os dados do curso, vamos dezipá-lo para acessar seu conteúdo interno:

unzip shell-lesson-data.zip
ls shell-lesson-data
cd shell-lesson-data
cd exercise-data

Dica: você não precisa escrever o nome do arquivo inteiro! Basta começar a escrever e pressionar ‘Tab’ que o prompt autocompletará.

Arquivos ocultos

Essa opção ‘..’ não está presente quando rodamos ‘ls’, mas ela está oculta em todos os diretórios e pode ser vista com:

ls -a

Assim como o ‘..’, que volta um passo na árvore de arquivos, também temos o ‘.’, que representa o diretório atual. Em algumas situações, também haverão alguns arquivos de configuração (como o .gitignore, comumente visto em repositórios do git).

Criar, mover, copiar e deletar arquivos

Para criar um diretório, você pode usar o comando ‘mkdir’, de make directory:

cd ../writing
mkdir thesis
ls

Regras básicas para nomear um diretório:

  • Não use espaços

  • Não comece com hífen (-)

  • Use apenas letras, números, ponto final, hífen, underscore

Se você precisa lidar com diretórios que não seguem essas regras, você pode colocar o nome deles entre aspas simples ’’ para mencioná-los em algum comando.

Criar um arquivo

Vamos criar um arquivo a partir do terminal:

cd thesis
touch draft.txt #cria arquivo sem abrir

mkdir files
cd files
code texto.txt #abre na IDE Visual Studio Code
nano rascunho.txt #abre no editor nano. Outras opções: vim, vi

Comandos do nano

  • Ctrl + O, Enter - salvar alterações no arquivo

  • Ctrl + X - sair do editor

  • Ctrl + ^ - modo de seleção de texto

  • Alt + 6 - copia

  • Ctrl + U - cola

Deletar arquivos

Como não vamos usar os arquivos criados em files, vamos removê-los usando ‘rm’, de remove:

rm texto.txt #deleta o arquivo
cd ..
rm files #irá retornar um erro
rm -rf files #para deletar um diretório e seus arquivos, é preciso das opções -rf (recursive,force)
#CUIDADO com esse comando! Não existe lixeira no Linux!!!!

Mover arquivos

O comando move é versátil e serve tanto para renomear arquivos quando para movê-los para outro caminho:

cd ~/Downloads/shell-lesson-data/exercise-data/writing #abrevia o caminho da Home
mv thesis/draft.txt thesis/quotes.txt #muda o nome de draft.txt para quotes.txt
ls thesis
mv thesis/quotes.txt . #movendo quotes.txt para o nosso diretório atual
ls thesis

Copiar arquivos

Podemos copiar arquivos usando o comando ‘cp’:

cp quotes.txt thesis/quotations.txt
cp -r thesis thesis_backup #podemos copiar recursivamente para gerar um arquivo de backup
ls thesis
ls thesis_backup

Fluxos de dados

Olhando para dentro dos arquivos

Agora que aprendemos a navegar diretórios, vamos mexer com arquivos. No diretório em que estamos, temos uma série de arquivos no formato Protein Data Bank (pdb). Vamos usar o comando ‘wc’, de word count:

wc cubane.pdb #linhas, palavras e caracteres no arquivo
wc -l #só linhas

Exibir conteúdo

Mas o que tem nesse arquivo?

cat cubane.pdb 

Se o seu arquivo for muito grande, é melhor usar um exibidor interativo:

less cubane.pdb 

Head e Tail

Às vezes, você só quer ver uma parte do arquivo. Você pode usar os comandos ‘head’ e ‘tail’:

head cubane.pdb
head -n 5 cubane.pdb
head -n 5 cubane.pdb ethane.pdb
tail cubane.pdb
tail -n 5 cubane.pdb

Redirecionamento

Podemos registar o output de um comando dentro de um arquivo por meio do símbolo ‘>’:

wc -l *.pdb > lengths.txt
cat lengths.txt

Agora, temos um arquivo chamado lengths.txt que possui o número de linhas de todos os arquivos .pdb do diretório.

Filtrar e ordenar os conteúdos de um arquivo

Nós podemos ordenar as linhas de um arquivo usando o comando ‘sort’:

sort -n lengths.txt
sort lengths.txt #nesse caso, o ordenamento será por ordem alfabética

E da mesma maneira, podemos direcionar o output do ordenamento para um novo arquivo:

sort -n lengths.txt > sorted-lengths.txt
head -n 1 sorted-lengths.txt

Obs.: em Shell, é uma péssima prática direcionar o output de uma operação para o mesmo arquivo, isso pode comprometer a integridade dele!

Passando o output para outro comando (pipe)

Em vez de criar vários arquivos intermediários que tornam o trabalho mais confuso, podemos direcionar o output de uma operação diretamente para outra usando o pipe ‘|’:

sort -n lengths.txt | head -n 1
wc -l *.pdb | sort -n | head -n 1

Exercício - Combinando múltiplos comandos

  • Volte ao Home Directory

  • Navegue até a pasta animal-counts, dentro de exercise-data e localize o arquivo animals.csv

  • Inspecione o arquivo. Quantas linhas ele tem? Qual o formato do dado dele?

  • Gere o arquivo exercicio.txt que ordena de forma alfabética reversa as 5 primeiras linhas do arquivo animals.txt e dispõe apenas os 3 últimos resultados da ordenação.

Automatizando tudo!

  • Loops e Scripts

Primeiro, quem é você?

Atividade de Pesquisa:

  • Doutorando em Bioinformática, UFRN
    • Metagenômica, transcriptômica e desenvolvimento de software no Dalmolin Group

Experiência de ensino:

Como repetir uma ação várias vezes?

  • Loops ou, em bom português, laços;

  • Como em qualquer outra linguagem, laços permitem que você realize uma mesma ação várias vezes, em sequência.

  • Mão na massa! Vamos supor que temos centenas de genomas, e queremos ver identificação de cada um desses bichos, que está na segunda linha de cada genoma. Você talvez pense em:

head -n 2 genoma.dat | tail -n 1
  • Mas nós temos centenas de arquivos!

Introduzindo laços

  • A estrutura geral de um laço simples em Bash é a seguinte:
# "para cada coisa na lista de coisas"
# coisa é um nome arbitrário!
for coisa in lista_de_coisas 
# A palavra "do" indica o início do bloco 
# da ação a ser realizada
do 
    # Não precisa indentar, mas ajuda.
    comando_a_executar $coisa 
# A palavra "done" indica o fim de um laço
done  

Ok e agora para os genomas?

  • Mesma coisa que antes, mas vamos usar dados “reais” agora:
for genoma in basilisk.dat minotaur.dat
do
     head -n 2 $genoma | tail -n 1
done
  • Ou, para saber a identificação para cada arquivo:
for genoma in basilisk.dat minotaur.dat
do
    echo $genoma
    head -n 2 $genoma | tail -n 1
done

Como salvar comandos para reutilizar depois?

  • A resposta: Scripts!
    • Arquivos de texto contendo código, que pode ser interpretado e re-executado múltiplas vezes.
  • Vamos supor que novos genomas continuam entrando no seu banco de dados, e agora você quer uma forma fácil de re-executar a identificação do genoma.
    • Vamos então fazer um script que execute os comandos anteriores.

Escrevendo um script

  • Existem inúmeros editores de texto possíveis, mas, se você está restrito à linha de comando, provavelmente usará:

    • nano
    • vim
  • Para motivos didáticos, utilizaremos o nano nos exemplos posteriores.

  • Vamos criar um novo script, para isso, execute:

nano identifica_genoma.sh

Escrevendo um script

  • Dentro do script, vamos colocar o comando anterior, mas vamos substituir uma parte:
head -n 2 $1 | tail -n 1
  • A variável $1 indica o primeiro argumento na linha de comando quando esse script é executado, ou seja, o genoma. Também podemos usar $2, $3, etc… $@ se refere a todos os argumentos.

  • Salve o arquivo, e agora podemos executá-lo como tal:

bash identifica_genoma.sh unicorn.dat

Uma breve tangente: Interpretadores e permissões

  • Você notou como usamos bash no comando anterior? Isso é um comando por si só, que diz que a linguagem bash deve interpretar o conteúdo textual do arquivo.

  • Mas isso pode ser ainda mais simples! Com apenas dois passos:

    • Inclua no seu arquivo um shebang:
    #!/bin/bash
    
    head -n 2 $1 | tail -n 1

Ok, mas e agora para executar?

  • Agora para executar seu programa propriamente dito, precisamos primeiro mudar suas permissões:
    • O comando chmod pode dar a qualquer arquivo de texto a capacidade de ser executado - Isso serve não só para bash, mas também Python, R, etc.
chmod +x identifica_genoma.sh
  • Agora podemos executar nosso script, com interpretadores e argumentos claramente definidos, assim:
./identifica_genoma.sh unicorn.dat
  • Nosso script agora virou um comando! Podendo ser utilizado em outros scripts!

Exercício - 10 minutos

  • Se direcione ao diretório exercise-data/alkanes

  • Lá, escreva um script chamado junta_pdb.sh. Esse script deve fazer um laço em todos os arquivos .pdb no diretório atual, concatenando todos eles em um único arquivo. Para isso, use o direcionador de saída >>.

  • Faça seu script executável (adicione o shebang e modifique as permissões).

Avançando nos comandos I

  • Grep e Expressões Regulares

O que danado é grep?

  • Global Regular Expression search and Print

  • Uma forma de achar padrões em arquivo de texto

    • Que padrões são esses? Expressões regulares.
  • Um uso comum de grep:

    # Buscar a palavra "Equus" em todos os arquivos .dat
    grep Equus *.dat
  • No entanto, grep se torna realmente poderoso quando usamos expressões regulares

O que são expressões regulares?

  • São formas de definir padrões de busca textual regrados.

  • Por exemplo, uma expressão regular para achar a palavra “Nossa” seria apenas a palavra propriamente dita. Mas para buscar “Nossa”, “Nosso”, “Nossas”, “Nossos”, você faria algo assim: Noss[a-zA-Z]*

    • Por exemplo com grep:
    grep "Noss[a-zA-Z]*" cancao_do_exilio.txt

Expressões regulares

  • Expressões regulares (ou regexes), podem ficar ainda mais complexas!
# Expressão regular para buscar um email numa sequência de texto
grep -E '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b' texto.txt
  • Não cobriremos grep e expressões regulares a fundo aqui, mas saiba que são essenciais para qualquer pessoa trabalhando na linha de comando, sobretudo para bioinformatas.
    • Esse site possui um tutorial interativo de regex caso queira aprender mais a respeito.

Mais sobre grep

  • O que mostramos aqui sobre grep é apenas o básico, grep pode ficar, assim como as regexes, ainda mais complexo! Dê uma olhada no seu manual (man grep) para saber mais a respeito. Mas aqui uma palhinha:
    • Vamos contar o número de ocorrências da palavra “terra” na Canção do Exílio:
    grep -c terra cancao_do_exilio.txt

Avançando nos comandos II

xargs

  • xargs é um comando que transforma a saída de outros comandos de forma a facilitar a execução encadeada. Pois a quebra de linhas ou espaços pode dificultar a execução de outro comando em sequência.
# Isso não funciona
ls *pdb | grep AUTHOR
# Isso funciona!
ls *pdb | xargs grep AUTHOR

GNU parallel

  • parallel é um comando que por padrão não vem em algumas distribuições, mas é super útil! Use ele para paralelizar a execução de comandos.

  • Por exemplo, vamos compactar vários arquivos .pdb:

ls *pdb | parallel gzip

Para aprender mais

Obrigado!