Programação Shell LinuxAqui temos um livro livre e completo sobre ShellOs sedentos do "saber livre" são muito benvindos. |
Comandos Shell Script |
||
Home | Artigos | Agradecimentos | Links Amigos | Comprar o livroChangelogs |
Papo de Botequim - Parte 1Papo de Botequim - Parte 2Papo de Botequim - Parte 3Papo de Botequim - Parte 4Papo de Botequim - Parte 5Papo de Botequim - Parte 6Papo de Botequim - Parte 7Papo de Botequim - Parte 8Papo de Botequim - Parte 9Papo de Botequim - Parte 10Papo de Botequim - Parte 11Tira Gosto |
Tira GostoShell em pedaços pequenos e gostososEm construção para sempreEsta página, apesar de estar no escopo do Papo de Botequim, nunca foi publicada na Linux Magazine. Trata-se de artigos que escrevi para outras mídias, dicas úteis que li pela internet afora (e neste caso com os devidos créditos), contribuições deste pessoal do Software Livre, maravilhoso e sempre pronto a ajudar e da imperdível Lista de Shell Script Passando parâmetros com xargs
Existe um comando, cuja função primordial é construir listas de parâmetros e passá-la para a execução de outros programas ou instruções. Este comando é o xargs [comando [argumento inicial]]
Exemplo:
Vamos procurar em todos os arquivos abaixo de um determinado diretório uma cadeia de caracteres usando o comando $ cat grepr
#
# Grep recursivo
# Pesquisa a cadeia de caracteres definida em $2 a partir do diretorio $1
#
find $1 -type f -print|xargs grep -l "$2"
Na execução deste script procuramos, a partir do diretório definido na variável Exatamente a mesma coisa poderia ser feito se a linha do programa fosse a seguinte: find $1 -type f -exec grep -l "$2" {} \; O primeiro processo tem duas grandes desvantagens sobre o anterior:
Aê pessoal do linux que usa o
ls colorido que nem porta de tinturaria: nos exemplos a seguir que envolvem esta instrução, você devem usar a opção --color=none , senão existem grandes chances dos resultados não ocorrerem como o esperado.
Vamos agora analisar um exemplo que é mais ou menos o inverso deste que acabamos de ver. Desta vez, vamos fazer um script para remover todos os arquivos do diretório corrente, pertencentes a um determinado usuário.
A primeira idéia que surge é, como no caso anterior, usar um comando find . -user cara -exec rm -f {} \;
Quase estaria certo, o problema é que desta forma você removeria não só os arquivos do ls -l | grep " cara " | cut -c55- | xargs rm
Desta forma, o
O xargs é também uma excelente ferramenta de criação de one-liners (scripts de somente uma linha). Veja este para listar todos os donos de arquivos (inclusive seus links) "pendurados" no diretório $ find /bin -type f -follow | \
xargs ls -al | tr -s ' ' | cut -f3 -d' ' | sort -u
Muitas vezes o Opções do xargsVocê pode usar as opções doxargs para construir comandos extremamente poderosos.
Opção -i
Para exemplificar isso e começar a entender as principais opções desta instrução, vamos supor que temos que remover todos as arquivos com extensão $ find . -type f -name "*.txt" | \
xargs -i bash -c "echo removendo {}; rm {}"
A opção Opção -n
Olha só a brincadeira que vamos fazer com o $ ls | xargs echo > arq.ls
$ cat arq.ls
arq.ls arq1 arq2 arq3
$ cat arq.ls | xargs -n1
arq.ls
arq1
arq2
arq3
Quando mandamos a saída do $ cat arq.ls | xargs -n 2
arq.ls arq1
arq2 arq3
Mas a linha acima poderia (e deveria) ser escrita sem o uso de pipe $ xargs -n 2 < arq.ls
Opção -p
Outra opção legal do $ ls dir
arq1.bug
arq1.ok
arq2.bug
arq2.ok
...
arq9.bug
arq9.ok
Para comparar os arquivos bons com os defeituosos, fazemos: $ ls | xargs -p -n2 diff -c
diff -c arq1.bug arq1.ok ?...y
....
diff -c arq9.bug arq9.ok ?...y
Opção -t
Para finalizar, o ResumoEntão podemos resumir o comando de acordo com a tabela a seguir:
Here StringsAcabei de dar um treinamento no Instituto de Pesquisas Eldorado, onde peguei uma turma de 12 alunos de altíssima qualidade. Devido ao preparo do pessoal, o nível do curso foi tão bom que cheguei a abordar alguns conceitos pouco usados como o redirecionamento por here strings.
Então pensei: se é uma coisa tão útil, porque não mostrá-la a todos? Ai vai ...
Primeiro um programador com complexo de inferioridade criou o redirecionamento de entrada e representou-o com um sinal de menor Brincadeiras a parte, o here strings é utilíssimo e, não sei porque, é um perfeito desconhecido. Na pouquíssima literatura que há sobre o tema, nota-se que o here strings é freqüentemente citado como uma variante do here document, teoria com a qual discordo pois sua aplicabilidade é totalmente diferente daquela. Sua sintaxe é simples: $ comando <<< $cadeia
Onde Como sempre, vamos direto aos exemplos dos dois usos mais comuns para que vocês próprios tirem suas conclusões.
Exemplos: $ a="1 2 3"
$ cut -f 2 -d ' ' <<< $a # Normalmente faz-se: echo $a | cut -f 2 -d ' '
2
$ echo $NomeArq
Meus Documentos # Arrrghhh!
$ tr "A-Z " "a-z_" <<< $NomeArq # Substituindo o echo $NomeArq | tr "A-Z " "a-z_"
meus_documentos
$ bc <<<"3 * 2"
6
$ bc <<<"scale = 4; 22 / 7"
3.1428
Para mostrar a melhoria no desempenho, vamos fazer um loop de 500 vezes usando o exemplo dados para o comando $ time for ((i=1; i<= 500; i++)); { tr "A-Z " "a-z_" <<< $NomeArq >/dev/null; }
real 0m3.508s
user 0m2.400s
sys 0m1.012s
$ time for ((i=1; i<= 500; i++)); { echo $NomeArq | tr "A-Z " "a-z_" >/dev/null; }
real 0m4.144s
user 0m2.684s
sys 0m1.392s
Veja agora esta seqüência de comandos com medidas de tempo: $ time for ((i=1;i<=100;i++)); { who | cat > /dev/null; }
real 0m1.435s
user 0m1.000s
sys 0m0.380s
$ time for ((i=1;i<=100;i++)); { cat <(who) > /dev/null; }
real 0m1.552s
user 0m1.052s
sys 0m0.448s
$ time for ((i=1;i<=100;i++)); { cat <<< $(who) > /dev/null; }
real 0m1.514s
user 0m1.056s
sys 0m0.412s
Observando este quadro você verá que no primeiro usamos a forma convencional, no segundo usamos um named pipe temporário para executar uma substituição de processos e no terceiro usamos here strings. Notará também que ao contrário do exemplo anterior, aqui o uso de here strings não foi o mais veloz. Mas repare bem que neste último caso o comando Vejamos uma forma rápida de inserir uma linha como cabeçalho de um arquivo: $ cat num
1 2
3 4
5 6
7 8
9 10
$ cat - num <<< "Impares Pares"
Impares Pares
1 2
3 4
5 6
7 8
9 10
Exemplos: $ echo "$Linha"
Leonardo Mello (21)3313-1329
$ cat -vet <<< "$Linha"
Leonardo Mello^I(21)3313-1329$ # Os separadores sao branco e <TAB> (^I)
$ read Nom SNom Tel <<< "$Linha"
$ echo "${Nom}_$S{Nom}_$Tel" # Vamos ver se ele leu cada um dos campos
Leonardo_Mello_(21)3313-1329 # Leu porque os separadores casavam com o IFS
Também podemos ler direto para um vetor (array) veja: $ echo $Frutas
Pera:Uva:Maçã
$ IFS=:
$ echo $Frutas
Pera Uva Maçã # Sem as aspas o shell mostra o IFS como branco
$ echo "$Frutas"
Pera:Uva:Maçã # Ahhh, agora sim!
$ read -a aFrutas <<< "$Frutas" # A opção -a do read, lê para um vetor
$ for i in 0 1 2
> do
> echo ${aFrutas[$i]} # Imprimindo cada elemento do vetor
> done
Pera
Uva
Maçã
Rotatório PeczenyjEstava, como faço todo dia, dando um lida nos e-mails da "Lista de Shell Script" , quando vi uma "descoberta" totalmente inusitada do Tiago Barcellos Peczenyj.
Quando resolvi montar esta coletânea de dicas, me lembrei disso e pedi-lhe para me encaminhar aquele e-mail novamente. O texto a a seguir é o e-mail que ele me mandou, só inseri o último exemplo e tirei as abreviaturas. Julio descobri uma forma para o Shell criar combinaçãoes fazendo rotação com os elementos estipulados. Podemos gerar todos os binários de 0000 a 1111 da seguinte forma: $ A={0,1}
$ eval echo $A$A$A$A
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Uma aplicação pratica que vejo é para combinar valores diferentes sem ter que encadear loops nem usar o $ A={`seq -s , -f "_%g" 3`}
$ eval echo -e $A$A$A |tr ' _' '\n ' | grep -vE '.+?(\b[0-9]+\b).+?\1'
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Neste caso eu combinei os números de 1 a 3 eliminando repetições com o
O 1 1 2 1 2 1 1 1 1não serão impressos.
Agora vai o meu exemplo: o one-liner a seguir gerará todas as permissões possíveis (em octal) para o arquivo $ A={`seq -s , 0 7`}
$ eval echo -e $A$A$A | tr ' ' '\n' | xargs -i bash -c "chmod {} arq; ls -l arq"
---------- 1 julio julio 100 2006-11-27 11:50 arq
---------x 1 julio julio 100 2006-11-27 11:50 arq
--------w- 1 julio julio 100 2006-11-27 11:50 arq
--------wx 1 julio julio 100 2006-11-27 11:50 arq
-------r-- 1 julio julio 100 2006-11-27 11:50 arq
-------r-x 1 julio julio 100 2006-11-27 11:50 arq
-------rw- 1 julio julio 100 2006-11-27 11:50 arq
-------rwx 1 julio julio 100 2006-11-27 11:50 arq
. . . . . . . . . . . . . . . . . .
-rwxrwxrw- 1 julio julio 100 2006-11-27 11:50 arq
-rwxrwxrwx 1 julio julio 100 2006-11-27 11:50 arq
Vamos ver este exemplo passo-a-passo para entendê-lo: $ echo $A
{0,1,2,3,4,5,6,7}
$ eval echo -e $A$A$A
000 001 002 003 004 005 006 007 010 ... ... 767 770 771 772 773 774 775 776 777
$ eval echo -e $A$A$A | tr ' ' '\n' # O tr trocará cada espaco em branco por um <ENTER>
000
001
002
003
. . .
774
775
776
777
A seguir o Aritmética em Shell
Antigamente usávamos o comando Exemplo: $ expr 7 \* 5 / 3 # 7 vezes 5 = 35 dividido por 3 = 11
14
Neste artigo porém, vamos ver outras formas não tanto conhecidas, porém mais simples de usar, mais elaboradas e com precisão maior. O uso do bcUma forma bacana de fazer cálculos em Shell – usada normalmente quando a expressão aritmética é mais complexa, ou quando é necessário trabalharmos com casas decimais – é usar a instrução calculadora do UNIX/LINUX. Obc . Veja como:
Exemplo: $ echo "(2 + 3) * 5" | bc # Parênteses usados para dar precedência
25
Para trabalhar com números reais (números não necessariamente inteiros), especifique a precisão (quantidade de decimais) com a opção $ echo "scale=2; 7*5/3" | bc
11.66
Outros exemplos: $ echo "scale=3; 33.333*3" | bc
99.999
$ num=5
$ echo "scale=2; ((3 + 2) * $num + 4) / 3" | bc
9.66
Obviamente todos os exemplos acima no caso de linux, poderiam (e deveriam) ser escritos usando Here Strings. Veja os últimos como ficariam: $ bc <<< "scale=3; 33.333*3"
99.999
$ num=5
$ bc <<< "scale=2; ((3 + 2) * $num + 4) / 3"
9.66
Uma vez apareceu na lista (excelente por sinal) de Shell script no Yahoo (http://br.groups.yahoo.com/group/shell-script/) um cara com a seguinte dúvida: "eu tenho um arquivo cujos campos estão separados por Mandei a seguinte resposta:
$ echo $(cut -f3 num | tr '\n' +)0 | bc
20.1
Vamos por partes para entender melhor e primeiramente vamos ver como era o arquivo que fiz para teste: $ cat num
a b 3.2
a z 4.5
w e 9.6
q w 2.8
Como pode-se ver, está dentro do padrão do problema, onde eu tenho como terceiro campo números reais. Vamos ver o que faria a primeira parte da linha de comandos, onde eu transformo os caracteres $ cut -f3 num | tr '\n' +
3.2+4.5+9.6+2.8+
Se eu mandasse desse jeito para o $ echo $(cut -f3 num | tr -s '\n' +)0
3.2+4.5+9.6+2.8+0
Isso é o que se costuma chamar one-liner, isto é, códigos que seriam complicados em outras linguagens (normalmente seria necessário criar contadores e fazer um loop de leitura somando o terceiro campo ao contador) e em Shell são escritos em uma única linha. Há também gente que chama isso de método KISS, que é o acrônimo de Keep It Simple Stupid. Mas o potencial de uso desta calculadora não se encerra aí, existem diversas facilidades por ela propiciadas. Veja só este exemplo: $ echo "obase=16; 11579594" | bc
B0B0CA
$ echo "ibase=16; B0B0CA " | bc # B, zero, B, zero, C, e A
11579594
Nestes exemplos vimos como fazer mudanças de base de numeração com o uso do Outras formas de trabalhar com inteiros
Outra forma muito legal de fazer cálculos é usar a notação Exemplo: Usando o mesmo exemplo que já havíamos usado: $ echo $(((2+3)*5)) # Os parênteses mais internos priorizaram o 2+3
25
Agora olha só esta maluquice: $ tres=3
$ echo $(((2+tres)*5)) # Variável tres não precedida pelo $
25
$ echo $(((2+$tres)*5)) # Variável tres precedida pelo $
25
Ué!! Não é o cifrão ( Preste a atenção nesta seqüência: $ unset i # $i mooorreu!
$ echo $((i++))
0
$ echo $i
1
$ echo $((++i))
2
$ echo $i
2
Repare que apesar da variável não estar definida, pois foi feito um
Repare que o Também são válidos: $ echo $((i+=3))
5
$ echo $i
5
$ echo $((i*=3))
15
$ echo $i
15
$ echo $((i%=2))
1
$ echo $i
1
Estas três operações seriam o mesmo que: i=$((i+3)) i=$((i*3)) i=$((i%2)) E isto seria válido para todos os operadores aritméticos o que em resumo produziria a tabela a seguir:
Mas o auge desta forma de construção com duplo parênteses é o seguinte: $ echo $var
50
$ var=$((var>40 ? var-40 : var+40))
$ echo $var
10
$ var=$((var>40 ? var-40 : var+40))
$ echo $var
50
Este tipo de construção deve ser lido da seguinte forma: caso a variável
Da mesma forma que usamos a expressão
Os operadores são os mesmos para estas três formas de construção, o que varia um pouco é a operação aritmética condicional com o uso do
$ echo $var
50
$ let var='var>40 ? var-40 : var+40'
$ echo $var
10
$ let var='var>40 ? var-40 : var+40'
$ echo $var
50
BaseandoSe você quiser trabalhar com bases diferentes da decimal, basta usar o formato: base#numero
Onde
Se $ echo $[2#11]
3
$ echo $((16#a))
10
$ echo $((16#A))
10
$ echo $((2#11 + 16#a))
13
$ echo $[64#a]
10
$ echo $[64#A]
36
$ echo $((64#@))
62
$ echo $((64#_))
63
Nestes exemplos usei as notações
Funciona também uma mudança automática para a base decimal, desde que você esteja usando a convenção numérica do C, isto é, em Exemplo $ echo $((10)) # decimal
10
$ echo $((010)) # octal
8
$ echo $((0x10)) # hexadecimal
16
$ echo $((10+010+0x10)) # Decimal + octal + hexadecimal
64
Ah, já ia me esquecendo! As expressões aritméticas com os formatos Testes usando expressões regularesNo Papo de Botequim 004, nós falamos tudo sobre comandos condicionais, mas faltou um que não existia àquela época. Neste mesmo Papo de Botequim, na seção E tome de test nós chegamos a falar de uma construção do tipo: [[ Expressao ]] && cmd
Onde o comando Exemplo: $ echo $BASH_VERSION # Conferindo se a versão do Bash é igual ou superior a 3.0.0
3.2.17(15)-release
$ Cargo=Senador
$ [[ $Cargo =~ ^(Governa|Sena|Verea)dora?$ ]] && echo É político
É político
$ Cargo=Senadora
$ [[ $Cargo =~ ^(Governa|Sena|Verea)dora?$ ]] && echo É político
É político
$ Cargo=Diretor
$ [[ $Cargo =~ ^(Governa|Sena|Verea)dora?$ ]] && echo É político
$
Vamos dar uma esmiuçada na Expressão Regular Colorindo a tela
Como você já havia visto no Papo de Botequim 007, o comando
Bem, agora você já sabe como especificar o par de cores, mas ainda não sabe as cores. A tabela a seguir mostra os valores que o
Neste ponto você já pode começar a brincar com as cores. - Mas peraí, ainda são muito poucas!
- É, tem toda razão... O problema é que ainda não lhe disse que se você colocar o terminal em modo de ênfase (
Exemplo Como exemplo, vejamos um script que mudará a cor de sua tela de acordo com sua preferência. $ cat mudacor.sh
#!/bin/bash
tput sgr0
clear
# Carregando as 8 cores básicas para um vetor Cores=(Preto Vermelho Verde Marrom Azul Púrpura Ciano "Cinza claro")
# Listando o menu de cores
echo "
Opc Cor
CL= until [[ $CL == 0[1-8] || $CL == [1-8] ]] do read -p " Escolha a cor da letra: " CL done # Para quem tem bash a partir da versao 3.2 #+ o test do until acima poderia ser feito #+ usando-se Expressoes Regulares. Veja como: #+ until [[ $CL =~ 0?[1-8] ]] #+ do #+ read -p " #+ Escolha a cor da letra: " CL #+ done CF= until [[ $CF == 0[1-8] || $CF == [1-8] ]] do read -p " Escolha a cor de fundo: " CF done let CL-- ; let CF-- # Porque as cores variam de zero a sete tput setaf $CL tput setab $CF clear Ganhando o jogo com mais coringasEstava eu lendo meus e-mails quando recebo um do Tiago enviado para a lista de Shell Script (já falei da lista e do Tiago no Rotatório Peczenyj). A seguir o conteúdo do e-mail:
Não sei se é conhecimento de todos mas o shell possui, alem do globbing normal (a expansão
Acho que, em alguns casos, podera ser BEM util, eliminando um pipe para um São eles: ?(padrao)Casa zero ou uma ocorrência de um determinado padrao
*(padrao)Casa zero ou mais ocorrências de um determinado padrao
+(padrao)Casa uma ou mais ocorrências de um determinado padrao
@(padrao)Casa com exatamente uma ocorrência de um determinado padrao
!(padrao)Casa com qualquer coisa, exceto com padrao
Para poder utilizá-lo precisa executar o $ shopt -s extglob
$ ls
file filename filenamename fileutils
$ ls file?(name)
file filename
$ ls file*(name)
file filename filenamename
$ ls file+(name)
filename filenamename
$ ls file@(name)
filename
$ ls file!(name) # divertido esse
file filenamename fileutils
$ ls file+(name|utils)
filename filenamename fileutils
$ ls file@(name|utils) # "lembra" um {name,utils}
filename fileutils
Usando o awk para pesquisar por equivalênciaAí vai mais uma que o Tiago mandou para a lista de Shell Script do Yahoo (já falei da lista e do Tiago no Rotatório Peczenyj e no Ganhando o jogo com mais coringa) Quem ja não passou por isso: Procurar uma palavra, porém uma letra acentuada, ou não, atrapalhou a busca?
Não descobri como fazer o Melhor explicar com um exemplo, onde vou listar o número da linha e a ocorrência casada: $ cat dados
éco
eco
èco
êco
ëco
eço
$ awk '/^eco/{print NR,$1}' dados
2 eco
$ awk '/^e[[=c=]]o/{print NR,$1}' dados
2 eco
6 eço
$ awk '/^[[=e=]]co/{print NR,$1}' dados
1 éco
2 eco
3 èco
4 êco
5 ëco
Ou seja, usar
A sintaxe é parecida com a das classes POSIX, trocando os dois-pontos Achei curioso e deve servir para algum caso semelhante ao descrito. find – Procurando arquivo por características
Se você está como o Mr. Magoo, procurando em vão um arquivo, use o comando find [caminho ...] expressão [ação] Parâmetros:
Os principais critérios de pesquisa definidos por expressão são:
Para usar mais de um critério de pesquisa, faça:
As principais ações definidas para
Exemplos:
Para listar na tela $ find . -name \*.sh Ação não especificada –print é default
./undelete.sh
./ntod.sh estes quatro primeiros arquivos foram
./dton.sh encontrados no diretório corrente.
./graph.sh
./tstsh/cotafs.sh
./tstsh/data.sh Estes quatro foram encontrados no
./tstsh/velha.sh diretório tstsh, sob o diretório corrente
./tstsh/charascii.sh
Preciso abrir espaço em um determinado file system com muita urgência, então vou remover arquivos com mais de um megabyte e cujo último acesso foi há mais de 60 dias. Para isso, vou para este file system e faço: $ find . –type f –size +1000000c –atime +60 –exec rm {} \;
Repare que no exemplo acima usei três critérios de pesquisa, a saber:
Repare ainda que entre estes três critérios foi usado o conector e, isto é, arquivos regulares e maiores que 1MByte e sem acesso há mais de 60 dias.
Para listar todos os arquivos do disco terminados por $ find / -name \*.sh –o –name \*.txt –print
Neste exemplo devemos salientar além das contrabarras
Com o
Também é possível formatar datas e horas obedecendo às tabelas a seguir:
Os três caracteres anteriores produzem uma data semelhante ao do comando Veja um exemplo: $ find . -name ".b*" -printf '%t %p\n'
Mon Nov 29 11:18:51 2004 ./.bash_logout
Tue Nov 1 09:44:16 2005 ./.bash_profile
Tue Nov 1 09:45:28 2005 ./.bashrc
Fri Dec 23 20:32:31 2005 ./.bash_history
Nesse exemplo, o
Essas datas também podem ser formatadas, para isso basta passar as letras da tabela anterior para maiúsculas (
Para melhorar a situação, vejamos uns exemplos; porém, vejamos primeiro quais são os arquivos do diretório corrente que começam por $ ls -la .b*
-rw------- 1 d276707 ssup 21419 Dec 26 17:35 .bash_history
-rw-r--r-- 1 d276707 ssup 24 Nov 29 2004 .bash_logout
-rw-r--r-- 1 d276707 ssup 194 Nov 1 09:44 .bash_profile
-rw-r--r-- 1 d276707 ssup 142 Nov 1 09:45 .bashrc
Para listar esses arquivos em ordem de tamanho, podemos fazer: $ find . -name ".b*" -printf '%s\t%p\n' | sort -n
24 ./.bash_logout
142 ./.bashrc
194 ./.bash_profile
21419 ./.bash_history
No exemplo que acabamos de ver, o $ find . -name ".b*" -printf '%TY-%Tm-%Td %TH:%TM:%TS %p\n' | sort
2004-11-29 11:18:51 ./.bash_logout
2005-11-01 09:44:16 ./.bash_profile
2005-11-01 09:45:28 ./.bashrc
2005-12-26 17:35:13 ./.bash_history
Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se. Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para mim. Valeu! |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Licença Creative Commons - Atribuição e Não Comercial (CC) 2009 Pelos Frequentadores do Bar do Júlio Neves. Todo o conteúdo desta página pode ser utilizado segundo os termos da Creative Commons License: Atribuição-UsoNãoComercial-PermanênciaDaLicença. |