-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.qmd
591 lines (397 loc) · 16.5 KB
/
index.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
---
title: "Introdução à Linha de Comando Linux"
author: "Julia Apolonio & João Cavalcante"
lang: pt
format:
revealjs:
theme: night
slide-number: true
footer: "Introdução à linha de comando do Linux"
chalkboard: true
multiplex: true # audience can follow along w/ mobile devices
fragments: true
logo: ./biome-shell-400.png
smaller: true
css: main.css
---
# Manipulando arquivos
## Um pouco sobre mim...
:::: {.columns}
::: {.column width="60%"}
Atividades de Pesquisa:
- Mestranda em Bioinformática, UFRN
- GWAS e desenvolvimento de software, orientada pela Dr. Vasiliki Lagou
Projetos em andamento:
- [Causeway: um pipeline para screening de genes efetores com Randomização Mendeliana e colocalização](https://github.com/juliaapolonio/MR_workflow)
- Descoberta de novos alvos de fármacos para depressão integrando GWAS multi-fenótipo e dados de QTL
:::
::: {.column width="40%"}
<center>

[LinkedIn](https://www.linkedin.com/in/juliaapolonio)
[Github](https://github.com/juliaapolonio)
</center>
:::
::::
## 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**.
## Navegando por arquivos e diretórios
Vamos começar!
Quando você abrir o *shell* pela primeira vez, você será apresentado ao ***prompt*** **de comando**, geralmente um cifrão, acompanhado de um cursor de texto. Em alguns sistemas operacionais é comum o prompt conter o nome do usuário e da máquina:
``` bash
biome@biome $
```
## Hello World!
Como todo curso de programação que se preze, vamos começar fazendo nosso 'hello world' em Shell:
``` bash
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 **l**i**s**tar, que lista os arquivos na pasta, ou diretório, atual:
``` bash
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 **P**rint **W**orking **D**irectory, você consegue ver o caminho absoluto para onde o seu prompt está apontando:
``` bash
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 **c**hange **d**irectory:
``` bash
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'.
``` bash
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:
``` bash
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:
``` bash
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á.
## Navegando para trás
Como voltar no sistema de arquivos?
``` bash
cd .. #volta uma etapa na arvore de arquivos
pwd
cd #volta para o home directory
pwd
cd Downloads/shell-lesson-data/north-pacific-gyre #caminho relativo
pwd
cd /home/juliaapolonio/Downloads/shell-lesson-data/exercise-data/alkanes #caminho absoluto
pwd
```
## 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:
``` bash
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 **m**a**k**e **dir**ectory:
``` bash
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:
``` bash
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 **r**e**m**ove:
``` bash
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 **m**o**v**e é versátil e serve tanto para renomear arquivos quando para movê-los para outro caminho:
``` bash
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':
``` bash
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 **w**ord **c**ount:
``` bash
wc cubane.pdb #linhas, palavras e caracteres no arquivo
wc -l #só linhas
```
## Exibir conteúdo
Mas o que tem nesse arquivo?
``` bash
cat cubane.pdb
```
Se o seu arquivo for muito grande, é melhor usar um exibidor interativo:
``` bash
less cubane.pdb
```
## Head e Tail
Às vezes, você só quer ver uma parte do arquivo. Você pode usar os comandos 'head' e 'tail':
``` bash
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 '\>':
``` bash
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':
``` bash
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:
``` bash
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 '\|':
``` bash
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ê?
:::: {.columns}
::: {.column width="60%"}
Atividade de Pesquisa:
- Doutorando em Bioinformática, UFRN
- Metagenômica, transcriptômica e desenvolvimento de software no [Dalmolin Group](https://dalmolingroup.github.io/)
Experiência de ensino:
- [Nextflow Ambassador](https://www.nextflow.io/ambassadors.html), Seqera
- Instructor, Anaconda Inc. ([Version Control with Git](https://learning.anaconda.cloud/version-control-with-git))
:::
::: {.column width="40%"}
<center>

[joao.bio.br](https://joao.bio.br/)
</center>
:::
::::
## 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:
```bash
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:
```bash
# "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:
```bash
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:
```bash
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:
```bash
nano identifica_genoma.sh
```
## Escrevendo um script
- Dentro do script, vamos colocar o comando anterior, mas vamos substituir uma parte:
```bash
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
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*:
```bash
#!/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.
```bash
chmod +x identifica_genoma.sh
```
- Agora podemos executar nosso script, com interpretadores e argumentos claramente definidos, assim:
```bash
./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, con`cat`enando 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?
- _**G**lobal **R**egular **E**xpression 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:
```bash
# 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:
```bash
grep "Noss[a-zA-Z]*" cancao_do_exilio.txt
```
## Expressões regulares
- Expressões regulares (ou *regexes*), podem ficar ainda mais complexas!
```bash
# 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](https://regexlearn.com/pt-br/learn/regex101) 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:
```bash
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.
```bash
# 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:
```bash
ls *pdb | parallel gzip
```
<center>
{width=400}
</center>
# Para aprender mais
- [Linux Journey](https://linuxjourney.com/change_locale/pt-BR)
- [Software Carpentry](https://swcarpentry.github.io/shell-novice/)
- [HackerRank](https://www.hackerrank.com/domains/shell)
# Obrigado!