| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • Buried in cloud files? We can help with Spring cleaning!

    Whether you use Dropbox, Drive, G-Suite, OneDrive, Gmail, Slack, Notion, or all of the above, Dokkio will organize your files for you. Try Dokkio (from the makers of PBworks) for free today.

  • Dokkio (from the makers of PBworks) was #2 on Product Hunt! Check out what people are saying by clicking here.

View
 

Shell_Script

Page history last edited by Sérgio Luiz Araújo Silva 12 years, 10 months ago


Introdução

Esta página contém uma série de scrips shell para usos diversos. Cadastre-se também na lista de shell script do yahoo http://br.dir.groups.yahoo.com/group/shell-script/ e descubra tudo que pode fazer com shell script

 

Listas e dicas

 

Scripts

 

Manual shell script

Essa apostila está em formato *.ps no kurumin linux use o comando ps2pdf para gerar um pdf.

 

ps2pdf aposhell.ps

 

Atalhos do konsole

 

^ ---> leia Control

^L ........... limpar a tela

^w ........... apagar palavra anterior

^e ........... vai para o final da linha

^a ........... vai para o começo da linha

^f ........... avança um caractere

^b ........... recua um caractere

Mf ........... avança uma palavra

Mb ........... recua uma palavra

^u ........... recorta do ponto atual até o começo da linha

^y ........... cola o que foi recortado

^d ........... faz logof

^k ........... recorta até o final da linha

^r ........... abre o histórico no modo de procura inversa

M.  .......... recupera o último parâmetro do último comando

 

modificando a variável $PS1

 

$PS1 é o prompt, veja um exemplo de configuração desta variável com cores

 

 export PS1='[�33[01;33m]t [�33[01;32m]u@h �33[01;34m]w $ [�33[00m]'/*{{{*//*}}}*/ 

 

 

Testando variáveis

 

#!/bin/ksh

# twofiles script handles two files named on the command line

# a usage function to display help for the hapless user
# plus an additional error message if it has been filled in

usage ()
{
	echo "twofiles"
	echo   "usage: twofiles file1 file2"
	echo   "Processes two files"
	echo " "
	echo $errmsg
}

# test if we have two arguments on the command line
if [ $# != 2 ]
then
	usage
	exit
fi

# test if file one exists and send an additional error message
# to usage if not found

if [ ! -f $1 ]
then
	errmsg=${1}": File Not Found"
	usage
	exit
fi

# same for file two
if [ ! -f $2 ]
then
        errmsg=${2}": File Not Found"
	usage
	exit
fi

# we are ok at this point so continue processing here

 

Comparando números

 

-eq Igual

!= Diferente

-gt Maior

-lt Menor

 

Mais comparações

 

-o Ou

-d Se for um diretório

-e Se existir

-z Se estiver vazio

-f Se contiver texto

-o Se o usuário for o dono

-r Se o arquivo pode ser lido

-w Se o arquivo pode ser alterado

-x Se o arquivo pode ser executado

 

Criando uma pasta rapidinho

 

 [ -d dir ] || mkdir dir ; cd dir

 

 

 

 

[-n] STRING
     Tamanho da String é diferente de zero
-z STRING
     Tamanho da String é zero
STRING1 = STRING2
     Strings são iguais
STRING1 != STRING2
     Strings não são iguais

NUMERO1 -eq NUMERO2
     NUMERO1 igual a NUMERO2

NUMERO1 -ge NUMERO2
     NUMERO1 igual e/ou mair que NUMERO2

NUMERO1 -gt NUMERO2
     NUMERO1 maior que NUMERO2

NUMERO1 -le NUMERO2
     NUMERO1 menor e/ou igual a NUMERO2

NUMERO1 -lt NUMERO2
     NUMERO1 menor que NUMERO2

NUMERO1 -ne NUMERO2
     NUMERO1 diferente de NUMERO2

if [ "texto" = "texto" ]; then
    echo "o texto é igual";
fi

if [ 1 -gt 5 ]; then
    echo "1 é maior que 5";
fi

if [ "a" = "3" ] || [ "a" = "b" ]; then
   echo "a não é igual a 3 ou c";
elif [ "a" = "c" ]  || [ "a" = "d" ]; then
   echo "a não é igual a c ou d";
else
   echo "A é diferente de 3,c,b,d";
fi

 

Testando se um arquivo está vazio

 

   [ -s arquivo ] && echo nao vazio || echo arquivo vazio

 

Permitindo somente uma instância de um script

Às vezes você tem um script e quer que ele não possa ser executado

mais de uma vez ao mesmo tempo. A solução

 

 

 LOCK_FILE=/tmp/.lock

(set -C; :  > $LOCK_FILE) 2> /dev/null
if [  $? != "0" ];  then
  echo "Lock File exists - exiting"
   exit 1
fi

# Do useful stuff
trap  'rm $LOCK_FILE' EXIT

 

Permitindo a execução somente pelo root

Há scripts que só podem ser executados pelo root

para verificar faça

 

 

# Check the script is being run by root
if  [ `id -u` != "0" ];  then
  echo "This script must be run as root"
  exit  1
fi 

 

#!/bin/bash

CONTADOR=0

while $CONTADOR -lt 10 ; do

 

echo "Contador em: $CONTADOR";

let CONTADOR=CONTADOR+1;

done

 

enquanto $CONTADOR menor que 10 ; faça

 

imprima "Contador em: $CONTADOR";

imcremente 1 no $CONTADOR;

feito

 

 

 

 

 

Estruturas

 

  case $1 in
     parametro1) comando1 ; comando2 ;;
     parametro2) comando3 ; comando4 ;;
     *) echo "Você tem de entrar com um parâmetro válido" ;;
  esac


  if [ -z $1 ]; then
     echo "Você tem de entrar com um parâmetro válido"
     exit
  elif [ $1 = "parametro1" ]; then
     comando1
     comando2
  elif [ $1 = "parametro2" ]; then
     comando3
     comando4
  else
     echo "Você tem de entrar com um parâmetro válido"
  fi


  for i in *
  do
     cp $i $i.backup
     mv $i.backup /usr/backup
  done

for original in *; do
   resultado=`echo $original |
              tr '[:upper:]' '[:lower:]'`
   if [ ! -e $resultado ]; then
      mv $original $resultado
   fi
done

 

 

O comando test

Os colchetes são um aliás para o comando test

 

 [[ string =~ regex ]]

# testa se o usuário digitou um parâmetro "$1"
if [ -z "$1" ]; then
  echo '   uso: matar programa '
  exit
fi


 

 

Um jeito direferente de usar o comando mkdir

 

mkdir -p teste/{docs/{img/{fotos/,wallpapers/,icons/},man/,textos/{bv/,teste/}}}

 

Exemplos

 

   ping -c 2 www.google.com > &> /dev/null && 
   echo "google respondeu" || echo "rost fora do ar"
   google respondeu

 

Somando números de 1 a 100

 

 seq -s+ 100 | bc

 

 

Controle de fluxo

 

 #!/bin/bash
 if [ -e $linux ]
 then
    echo 'A variável $linux existe.'
 else
   echo 'A variável $linux não existe.'
 fi

Exemplo usando operadores

#!/bin/bash
a=1
b=2

if [ $a -lt $b ]
then
   echo '$a é menor que $b!'
elif [ $a -gt $b ]
then
   echo '$a é maior que $b!'
elif [ $a -eq $b ]
then
   echo '$a é igual a $b!'
fi

====================

Gerador de números aleatórios

====================

 

   echo $((RANDOM%Limite))
Onde limite+1 é até que número o shell deverá gerar números aleatórios

E se quiser armazenar o valor gerado:
   Valor=$((RANDOM%Limite))

  $((RANDOM%5+1))
gera números de 1 a 5

===================================
Para gerar um número aleatório entre -10 e 10
number=$(($((RANDOM%21))-10))

====================

Fluxo com o for

====================

 

for i in *
do
   cp $i $i.backup
   mv $i.backup /usr/backup
done

====================

 #!/bin/bash
 if [ -e $linux ]
 then
    echo 'A variável $linux existe.'
 else
   echo 'A variável $linux não existe.'
 fi

Exemplo usando operadores

#!/bin/bash
a=1
b=2

if [ $a -lt $b ]
then
   echo '$a é menor que $b!'
elif [ $a -gt $b ]
then
   echo '$a é maior que $b!'
elif [ $a -eq $b ]
then
   echo '$a é igual a $b!'
fi

 

=====================

Fluxo com while

=====================

 

O while testa continuamente uma expressão, até que ela se torne falsa. Exemplo:

variavel="valor"
while [ $variavel = "valor" ]; do
   comando1
   comando2
done

 

 

Ufa! Como você viu tem coisa prá chuchu, e como eu te disse no início,

o nosso if é muito mais poderoso que o dos outros. Vamos ver em uns

exemplos como isso tudo funciona, primeiramente testaremos a

existência de um diretório:

 

Exemplos:

 

 

if test -d lmb

then

cd lmb

else

mkdir lmb

cd lmb

fi

 

No exemplo, testei se existia um diretório lmb definido, caso negativo

(else), ele seria criado. Já sei, você vai criticar a minha lógica

dizendo que o script não está otimizado. Eu sei, mas queria que você o

entendesse assim, para então poder usar o ponto-de-espantação (!) como

um negador do test. Veja só:

 

 

if test ! -d lmb

then

mkdir lmb

fi

cd lmb

 

e utilizando a nova sintaxe, vamos fazê-lo assim:

 

 

if ! -d lmb

then

mkdir lmb

fi

cd lmb

 

 

Isso também poderia ser escrito da seguinte maneira:

 

 

! -d lmb && mkdir lmb

cd dir

 

Ou ainda retirando a negação (!):

 

 

-d lmb || mkdir lmb

cd dir

 

Neste caso, se o cd fosse mal sucedido, seria criado o diretório lmb

mas não seria feito o cd para dentro dele. Para executarmos mais de um

comando desta forma, é necessário fazermos um grupamento de comandos,

e isso se consegue com o uso de chaves ({ }). Veja como seria o

correto:

 

 

cd lmb ||

{

mkdir lmb

cd lmb

}

 

Ainda não está legal, porque caso o diretório não exista, o cd dará a

mensagem de erro correspondente. Então devemos fazer:

 

 

cd lmb 2> /dev/null ||

{

mkdir lmb

cd lmb

}

 

 

==============================================

Para pegar uma variável digitada pelo usuário

==============================================

 

read -p "digite o seu nome: " nome

 

Combinando comandos

O arquivo de configuração do estilos do firefox (para páginas) é nomeado como: userContent.css para buscalo uso o parâmetro '-iname' do find, mas às vezes mantenho cópias em outros locais, para evitar erros busco em minha pasta pessoal por uma pasta que tem um número aleatório no começo e no final a palavra default.

 

cp $(find ~/ -iname usercontent.css | grep default) /home/sergio/Desktop/

 

 

 

 

 

 

 

Arrays

O que você quer fazer? O BASH não oferece funções para tratar arrays.

Mas um array é algo assim:

 

$ array=( A B C D )

$ echo ${array[0]}
A

$ echo ${array[1]}
B

$ echo ${array[@]}
A B C D

VAR=($(ls *.html))  --> gera um array

 echo ${VAR[0]}

 

=====================================

Script para criar 100 arquivos txt

=====================================

 

#!/bin/bash

for ((i=1; i<=100; i++)); {
     touch arquivo${i}.txt
     echo "arquivo${i}.txt" >> arquivo${i}.txt
}

 

 

 

============================================================

Grupos de comandos Expansão de strings e nomes de arquivos

============================================================

 

O Bash permite agrupar comandos, que desse modo são executados como uma única
unidade. Podemos agrupar os comandos de duas formas:

1) Agrupamento por parênteses, "( )": Comandos colocados entre parênteses e
separados por ponto-e-vírgula, ";", são agrupados e executados serialmente
invocando um subshell. Exemplo:

# (ls; du; find -name *.txt)   

2) Agrupados por chaves, "{ }":

Comandos colocados entre chaves e separados por ponto-e—vírgula, ";", são
agrupados e executados serialmente no shell corrente. Exemplo:

# {ls; du; find -name *.txt}

Você deve estar pensando: "Para que eu agruparia meus comandos? Para deixá-los mais bonitos?" Não!

A vantagem de vários comandos agrupados pode ser vista quando precisamos
desviar a saída desses comandos. Imagine que você precise fazer um script para
executar vários comandos e obter a saída de erros de cada comando colocado no
script. Seria assim:

...
comando1 2>erros.txt
comando2 2>>erros.txt
comando3 2>>erros.txt
comando4 2>>erros.txt
...

Com o agrupamento isso fica mais fácil e simples:

...
(
comando1 ; 
comando2 ;
comando3 ;
comando4 ;
) 2>erros.txt
...

Observe que no primeiro exemplo desviamos o erro para cada comando e no segundo
exemplo o desvio foi feito para todos os comandos em uma única vez.

Se esse exemplo fosse passado para a linha de comando ficaria desta forma: exemplo 1:

# comando1 2>erros.txt; comando2 2>>erros.txt ; comando3 2>>erros.txt comando4 >>erros.txt

exemplo 2:

#(comando1;comando2;comando3;comando4;) 2> erros.txt

Você concorda que, com agrupamento, a linha de comando fica até mais legível!
Agora vamos imaginar que você precise tratar a saída de vários comandos, por
exemplo, alterar de minúsculo para maiúsculo. Você poderia escrever assim:

# cat /etc/hosts | tr a-z A-Z > saida.txt ; 
cat /etc/resolv.conf |tr a-z A-Z >>saida.txt ; 
cat /etc/sysconfig/network | tr a-z A-Z >>saida.txt

Mas o ideal seria:

# (cat /etc/hosts ; cat /etc/resolv.conf ; 
cat /etc/sysconfig/network; )| tr a-z A-Z >>saida.txt

No segundo exemplo, além de ficar mais legível, o comando "tr" é executado uma
única vez, já no primeiro exemplo cada um dos comandos será executado.

A diferença entre os grupos criados com parênteses, "( )", ou os criados com
chaves, "{ }", pode ser vista no comando abaixo:

# VAR="ANTES";(VAR="DEPOIS";VAR="ADIANTE";); echo $VAR
ANTES

# VAR="ANTES";{VAR="DEPOIS";VAR="ADIANTE";}; echo $VAR
ADIANTE

Observe que no exemplo escrito com parênteses a variável VAR retornou ao mesmo
valor que fora atribuído antes de executar o grupo de comandos. Isso se deve ao
fato de que os comandos são executados em subshell. Já no exemplo escrito com
chaves a variável VAR retornou ao último valor que fora atribuído, porque
grupos feitos com chaves são executados no shell corrente.

Expansão de strings

Expansão de strings é um mecanismo que combina uma expressão inicial com um
conjunto de caracteres. Exemplo:

#echo a{1,2,3}
a1 a2 a3

As combinações são feitas entre os elementos que estão entre as chaves
separados por vírgula, da esquerda para a direita.

Podemos combinar mais que um conjunto de caracteres simultaneamente:

# echo a{1,2,3}b{1,2,3}
a1b1 a1b2 a1b3 a2b1 a2b2 a2b3 a3b1 a3b2 a3b3

Combinar dois conjuntos separadamente também é possível, basta colocar os
conjuntos entre chaves e separá-los por vírgula.

# echo {a{1,2,3},b{1,2,3}}
a1 a2 a3 b1 b2 b3

A grande vantagem da expansão está na expansão de nomes de arquivos, que é
utilizada em comandos que recebem como parâmetro um ou mais nome de arquivos.
Exemplo:

# ls /dev/hda
| |––> Este é o parâmetro do ls que deve ser um diretório ou um arquivo Imagine
que você queira listar todos os arquivos do diretório /dev que inicie com hda e
termine com 1, 2 ou 3.

# ls /dev/hda{1,2,3}
/dev/hda1 /dev/hda2 /dev/hda3


Podemos combinar dois conjuntos também:

# ls /dev/{hda{1,2,3},hdb{1,2,3}}

/dev/hda1 /dev/hdb1
/dev/hda2 /dev/hdb2
/dev/hda3 /dev/hdb3

Adicionar metacaracteres também é possível:

# ls /dev/{hd?{1,2,3}}
/dev/hda1 /dev/hdb1 /dev/hdc1 /dev/hdd1
/dev/hda2 /dev/hdb2 /dev/hdc2 /dev/hdd2
/dev/hda3 /dev/hdb3 /dev/hdc3 /dev/hdd3


Os metacaracteres suportados em expansão são:

* — Um ou mais caracteres

# ls /dev/{hd{a,b,c}*}
/dev/hda1 /dev/hdb1 /dev/hdc1 
/dev/hda11 /dev/hdb11 /dev/hdc11 
/dev/hda2 /dev/hdb2 /dev/hdc2 
/dev/hda3 /dev/hdb3 /dev/hdc3


? — Exatamente um caractere

# ls /dev/{hd{a,b,c}?}
/dev/hda1 /dev/hdb1 /dev/hdc1 
/dev/hda2 /dev/hdb2 /dev/hdc2 
/dev/hda3 /dev/hdb3 /dev/hdc3


[abc] — Combina com a, b ou c

# ls /dev/{hd[abc]{1,2,3}}
/dev/hda1 /dev/hdb1 /dev/hdc1
/dev/hda2 /dev/hdb2 /dev/hdc2
/dev/hda3 /dev/hdb3 /dev/hdc3


[a-z] — Combina o range de "a" a "z"

# ls /dev/{hd[a-c]{1,2,3}}
/dev/hda1 /dev/hdb1 /dev/hdc1
/dev/hda2 /dev/hdb2 /dev/hdc2
/dev/hda3 /dev/hdb3 /dev/hdc3


[!a-z] — Não combina o range de "a" a "z"

# ls /dev/{hd[!a-c]{1,2,3}}
/dev/hdd1 /dev/hde1 /dev/hdf1
/dev/hdd2 /dev/hde2 /dev/hdf2
/dev/hdd3 /dev/hde3 /dev/hdf3

Espero ter contribuído mais um pouco para o aprendizado dos leitores.

Até a próxima edição!

 

Fazendo testes antes de executar um script

fonte: http://br.geocities.com/cesarakg/tips-shell-programming.html

 

Testando argumentos de linha de comando e modo de usar

Quando você escreve um shell script, os argumentos são normalmente necessários para que o script funcione corretamente. Para garantir que os argumentos façam algum sentido, é geralmente necessário validar os mesmos.

Testar para ver se há argumentos suficientes é geralmente o método mais fácil de validação. por exemplo, se você criou um script shell que pede dois nomes de arquivos para operar, teste a existência de dois argumentos na linha de comando. para fazer isto no Bourne e no Korn shell, verifique o valor de $# -- uma variável que contém a contagem de argumentos, além do próprio comando. É também uma boa pratica incluir uma mensagem que detalhe as razões por que o comando falhou. Isto é criado em uma função usage.

O script twofiles abaixo, testa se há dois argumentos na linha de comando:

#!/bin/ksh

# twofile script handles two files named on the command line

# a usage function to display help for the hapless user

usage ()
{
	echo "twofiles"
	echo   "usage: twofiles file1 file2"
	echo   "Processes two files"
}

# test if we have two arguments on the command line
if [ $# != 2 ]
then
	usage
	exit
fi

Uma prática mais segura é validar o máximo que você puder antes de executar alguma coisa. A seguinte versão de twofiles verifica a contagem de argumentos e testa os dois arquivos. Se o arquivo 1 não existe ( if [ ! -f $1 ]) uma mensagem de erro é configurada, uma mensagem de uso é apresentada, e o programa termina. O mesmo é feito para o arquivo 2:

#!/bin/ksh

# twofiles script handles two files named on the command line

# a usage function to display help for the hapless user
# plus an additional error message if it has been filled in

usage ()
{
	echo "twofiles"
	echo   "usage: twofiles file1 file2"
	echo   "Processes two files"
	echo " "
	echo $errmsg
}

# test if we have two arguments on the command line
if [ $# != 2 ]
then
	usage
	exit
fi

# test if file one exists and send an additional error message
# to usage if not found

if [ ! -f $1 ]
then
	errmsg=${1}": File Not Found"
	usage
	exit
fi

# same for file two
if [ ! -f $2 ]
then
        errmsg=${2}": File Not Found"
	usage
	exit
fi

# we are ok at this point so continue processing here

Note que no Korn shell você pode usar a sintaxe de teste de colchetes duplos, que é mais rápida. O colchete simples na verdade chama um programa test para testar os valores, enquanto que com o colchete duplo o teste é implementado no Korn shell e não precisa chamar um programa separado.

O teste de colchete duplo não funciona no Bourne shell:

if [[ $# != 2 ]]

ou

if [[ ! -f $1 ]]

ou

if [[ ! -f $2 ]]

Esta validação pode evitar erros posteriores na lógica do programa quando subitamente percebe-se que um arquivo está faltando. Considere isto como uma boa prática de programação.

 

Atalhos do bash

 

ATALHOS DO BASH

Ctrl + Alt + BackSpace : reinicia o X

Ctrl + Alt + Del : reinicia o sistema em modo texto

Ctrl + Alt + F''x'' : muda o shell (F1 – F6 (texto), F7 (gráfico))

Alt + F''x'' : alterna o shell (modo texto)

Alt + B : move o cursor do console para a palavra anterior

Alt + F : move o cursor do console para a palavra seguinte

Ctrl + A : vai para o início da linha

Ctrl + E : vai para o fim da linha

Ctrl + C : pára o comando

Ctrl + D : logout

Ctrl + W : apaga do cursor até o início da palavra

Ctrl + U : apaga do cursor até o início da linha

Ctrl + K : apaga do cursor até o fim da linha

Ctrl + L : clear

Ctrl + R : busca incremental no hitórico de comandos

Ctrl + T : inverte caractere sob o cursor com o anterior

Ctrl + Y : re-inserir o último texto apagado

Ctrl + Z: colocar processo em background

Shift + Page(UP/DOWN) : navega pelo shell

!''x'': repete o último comando (onde ''x'' é o comando a ser chamado – Exemplo: !mount)

TAB : autocompletar 

Criando uma árvore de diretórios com um único comando

 

  mkdir -p {.wiki/,.vim/{plugin/,syntax},docs/{img/{fotos/,wallpapers/,icons},textos/{artigos/,man/{shell/,vim/,}}}}

No comando acima são criadas três pastas

 .wiki (oculta)
 .vim - contendo as subpastas plugin e syntax
 docs contendo: img (fotos wallpapers e icons) textos contendo (argigos) e (man (shell e vim)

 

Como guardar variáveis em arquivos

 

 use  . /caminho/para/arquivo

Note o espaço entre o ponto e a barra

 

Usando cores

Fonte: http://www.vivaolinux.com.br/artigos/impressora.php?codigo=1908

 

 echo -e "Viva o �33[01;32mLinux�33[01;37m"

Observem no exemplo os trechos em negrito e reparem que são eles um dos temas do nosso artigo. Tentarei explicar o que vemos:

    * "�33": ainda não consegui encontrar o real motivo de usar isto, mas é obrigatório para usar as cores, se trocar por outra coisa dará tudo errado;
    * "01"( estilo): significa que nosso texto será em negrito (bold);
    * "32m" (cor do texto): 32 representa a cor vermelha e o "m" indica o fim da expressão e após ele você já poderá incluir o texto que bem desejar; 

Meio complicado ainda né!? Mas vai abaixo os dados que certamente irão ajudar a se organizar:

 

Estilos Cores de texto Cores de fundo
00: Nenhum 30: Preto 40: Preto
01: Negrito 31: Vermelho 41: Vermelho
04: Sublinhado 32: Verde 42: Verde
05: Piscante 33: Amarelo 43: Amarelo
07: Reverso 34: Azul 44: Azul
08: Oculto 35: Magenta (Rosa) 45: Magenta (Rosa)
  36: Ciano (Azul Ciano) 46: Ciano (Azul Ciano)
  37: Branco 47: Branco

 

Filtrando linhas de um arquivo

 

Re: [shell-script] Filtrar linhas no arquivo texto

Acho que um sed + ER fica legal:

$ cat test
documento_0012526A.odt
documento_0035555A.odt
documento_0054443A.odt
documento_0022222A.odt
documento_0034344A.odt
documento_0055555A.odt

$ sed 's/^documento_(.*).odt$/1/' test
0012526A
0035555A
0054443A
0022222A
0034344A
0055555A

 

Named Pipes

Fonte: http://www.dicas-l.com.br/cantinhodoshell/cantinhodoshell_20070520.php

Autor: Júlio César Neves

 

  $ cat <(ls -l)

Resultará no comando ls -l executado em um subshell como é normal, porém redirecionará a saída para um named pipe temporário, que o Shell cria, nomeia e depois remove. Então o cat terá um nome de arquivo válido para ler (que será este named pipe e cujo dispositivo lógico associado é /dev/fd/63), e teremos a mesma saída que a gerada pela listagem do ls -l, porém dando um ou mais passos que o usual. 

Veja mais...

 

veja também

 

Comments (0)

You don't have permission to comment on this page.