Assine a Lista Dicas-L
Receba diariamente por email as dicas
de informática publicadas neste site
Para se descadastrar, clique aqui.
Maus hábitos em bash
Colaboração: Rubens Queiroz de Almeida
Data de Publicação: 28 de julho de 2010
Frequentemente, fazemos uso incorreto de comandos em bash. Não que faça muita diferença, mas não custa nada aprendermos algumas regrinhas, que tornarão o nosso código mais eficiente e legível.
Comando cat
Muitos de nós (eu inclusive) temos o hábito de fazer coisas como:
cat arquivo.txt | wc -l
O comando cat significa catenate, que significa concatenar. Se eu tenho apenas um arquivo, não preciso do cat, posso usar o wc diretamente:
wc -l arquivo.txt
Já se eu quisesse contar o número de linhas em diversos arquivos, eu poderia usar o cat com o comando wc:
cat arquivo1.txt arquivo2.txt arquivo3.txt | wc -l
Mas tudo irá depender do que se quer fazer. O comando wc também pode ser usado com esta finalidade, mas a saída é ligeiramente diferente:
$ wc -l /etc/passwd /etc/hosts
39 /etc/passwd
12 /etc/hosts
51 total
Com o cat:
$ cat /etc/passwd /etc/hosts | wc -l 51
O comando wc é mais falante e se eu faço uso deste recurso em uma situação em que preciso apenas do número de linhas, esta verbosidade precisará ser tratada de alguma forma, o que é desnecessário.
Comando ls
Um erro bem comum:
for arquivo in `ls *` do ... done
Eu não preciso usar o ls para obter uma listagem dos arquivos em um diretório neste trecho. Eu posso fazer assim:
for arquivo in * do ... done
Uma outra variação desta prática, com o comando cat:
cat `ls *`
Porque não fazer assim?
cat *
Cuidado com o rm
Quem nunca fez algo assim?
rm -rf ~/ *.trash
O que a pessoa queria? Remover de seu diretório pessoal todos os arquivos terminados em trash. O que aconteceu? Este infeliz removeu todo o seu diretório pessoal e apagou os arquivos terminados em trash do diretório corrente. O causador de tudo isto foi o espaço em branco entre ~/ e *.trash. A pressa é inimiga da perfeição :-(
Na verdade o que ele queria era:
rm -rf ~/*.trash
while ou for?
Vejamos:
for f in `cat arquivo.txt`
do
...
done
Podemos fazer também assim:
while read f do ... done < arquivo.txt
Na primeira opção, o resultado do comando `cat arquivo.txt`, pode ser uma linha mais longa do que o seu sistema pode tratar, o que pode trazer resultados indesejáveis.
Referências
- Useless Use of Cat Award - grande parte desta dica foi baseada nesta página. Leitura obrigatória, com diversos outros exemplos interessantes.
- Useless use of cat
- Shell Script Profissional - O livro Shell Script Profissional, de autoria do Aurélio Marinho Jargas, é referência obrigatória para quem deseja programar como gente grande :-) Vale cada centavo!
Referências Adicionais
Referências adicionais sobre os assuntos abordados neste site podem ser encontradas em nossa Bibliografia.
Avalie esta dica
Opinião dos Leitores
09 Ago 2010, 11:41
$cat /etc/passwd | less
pode ser usado diretamente:
$less /etc/passwd
O exemplo do "for + ls" também é muito usado pelos menos experientes.
Graças a esse post já não tenho mais esse mau habito.
02 Ago 2010, 21:58
$ cd /pub
$ more beer
30 Jul 2010, 14:40
cat arquivo.txt | grep "palavra"
ao invés de apenas:
grep "palavra" arquivo.txt
28 Jul 2010, 19:25
É interessante testar essas dicas com o comando time, fica claro como os maus hábitos podem contribuir para um desempenho precário em scripts.
Valeu.
28 Jul 2010, 08:29
awk -F":" '/user/ {print $1}' /etc/passwd
28 Jul 2010, 01:32
por que o array v tem comportamento distinto nos dois laços?
cat foo | while read i; do v=(${v[*]} $i); done
for i in $(cat bar); do v=(${v[*]} $i); done
BASH_VERSION='4.1.5(1)-release'




