Este é o histórico da linha de comando de uma palestra que fiz para funcionários da Conectiva, sobre Shell Script. O objetivo não era ensinar Shell, mas sim passar dicas e sanar as dúvidas dos participantes, que já conheciam a linguagem e já faziam scripts.
- Data: 04-Dez-2003
- Local: Auditório da Conectiva, Curitiba
- Duração: 2 horas
- Requisitos: Conhecer o shell, já ter feito scripts
Shell scripts no sistema (exemplos!)
$ cd /usr/bin $ file * | grep -i shell $ vi xtrace
Como executar um script (chmod)
$ cd /tmp $ vi teste.sh $ ./teste.sh $ ls -l teste.sh $ chmod +x teste.sh $ ls -l teste.sh $ ./teste.sh $ vi teste.sh $ which sh $ l /bin/sh $ vi teste.sh $ ./teste.sh $ vi teste.sh
Expansão de variáveis com ${VAR:-} e amigos
$ a="abcde" $ echo $a $ echo ${a} $ echo ${#a} $ echo ${a:-FOO} $ unset a $ echo $a $ echo ${a:-FOO} $ if [ -z "$a" ]; then a=FOO ; fi $ unset a $ echo $a $ echo ${a:-FOO} $ echo ${a:=FOO} $ echo $a $ echo ${a:+FOOoooooooo}
Expansão avançada do bash2 (tipo sed)
$ echo $a $ echo ${a/O/.} # sed s/// $ echo ${a//O/.} # sed s///g $ echo $a | sed 's/O/./g' $ echo ${a//O/.tyturtu} $ rpm -q bash $ b=O $ echo ${a//$b/.}
Eval
$ a="ls" $ echo $a $ eval $a $ ${!a} $ : ${!a} $ echo ${!a}
Diferença do echo com aspas (mantém espaços) e sem
$ echo ahyi dfy dfui yidfs dfis ui fd yifsdy idfsy isdf $ echo "ahyi dfy dfui yidfs dfis ui fd yifsdy idfsy isdf" $ a="ahyi dfy dfui yidfs dfis ui fd yifsdy idfsy isdf" $ echo $a $ echo "$a" $ cat /etc/fstab $ cat /etc/fstab | grep swap $ cat /etc/fstab | grep swap | sed -n l $ var=$(cat /etc/fstab | grep swap) $ echo $var $ echo "$var"
Subshell com crase ou $(), prefira o $()
$ var=`date` $ echo $var $ var=$(date) $ echo $var $ var=$(echo `cat /etc`)
As aspas simples protegem, não expandem vars nem comandos
$ a="abc" $ echo $a $ echo "$a" $ echo '$a' $ echo '$a $(date)' $ echo "$a $(date)"
Ao definir uma variável não pode ter espaços!
$ a = ''
O pesadelo dos escapes...
$ a='\' $ echo $a $ a="\" $ echo $a $ echo \$a $ a="\" $ " $ a=' \' ' $ a="\\" $ echo $a
O sed e os escapes (use o echo para ajudar!)
$ echo "//bla//" # mudar para \\bla\\ $ echo "//bla//" | sed "s///\/" $ echo "//bla//" | sed "s/\//\\/" $ echo "s/\//\\/" $ echo 's/\//\\/' $ echo "//bla//" | sed 's/\//\\/' $ echo "//bla//" | sed 's/\//\\/g' $ a='/' $ echo "//bla//" | sed "s/$a/\\/g" $ echo "s/$a/\\/g" $ a="\\/" $ echo $a $ echo "//bla//" | sed "s/$a/\\/g" $ echo "s/$a/\\/g" $ echo "//bla//" | sed "s/$a/\\\/g" $ $(echo "//bla//" | sed "s/$a/\\\/g") $ echo $(echo "//bla//" | sed "s/$a/\\\/g")
O sed pode usar qualquer delimitador fora o s///
$ echo isso | sed s/isso/aquilo/g $ echo isso | sed s,isso,aquilo,g $ echo isso | sed s isso aquilo g $ echo isso | sed 's isso aquilo g' $ echo isso | sed 's9isso9aquilo9g' $ echo isso | sed 's > isso > aquilo > g' $ echo isso | sed 's|isso|aquilo|g' $ echo isso | sed 'sáissoáaquiloág' $ echo isso | sed 's§isso§aquilo§g' $ echo isso | sed 's"isso"aquilo"' $ echo isso | sed 's isso aquilo' $ echo isso | sed 's isso aquilo '
Como "ver" se é um TAB ou espaços
$ echo -e "\ta\ta" $ echo -e "\ta\ta" | sed -n l $ echo -e "\ta\ta" | od -c $ echo -ne "\ta\ta" | od -c $ echo -n "bla" $ echo -ne "bla\n" $ echo "bla"
Como depurar (debug) scripts: sh -x, set -x, ...
$ sh -x teste.sh $ sh teste.sh $ vi teste.sh $ ./teste.sh $ set -x $ ./teste.sh $ echo $ vi teste.sh $ ./teste.sh $ vi teste.sh $ set +x $ vi teste.sh
Como pegar a saída de erro (STDERR, 2)
$ cp $ cp | grep arqu $ ls > foo $ cat foo $ cp > foo $ cat foo $ cp 1> foo $ cp 1> foo 2> foo $ cat foo $ cp 2> foo $ ./teste.sh $ ./teste.sh 2> foo $ ./teste.sh > foo $ ./teste.sh > foo 2> foo $ cat foo $ ./teste.sh > foo 2>&1 $ cat foo $ ./teste.sh > foo 2>&1 $ ./teste.sh 2>&1 $ cp $ cp 2>&1 $ cp 2>&1 | grep arqui
O comando test, seu sósia [ e o código de retorno $?
$ if [ $var = 'abc' ] ; then echo OK ; fi $ which [ $ l /usr/bin/[ $ if test $var = 'abc' ; then echo OK ; fi $ if grep -qs root /etc/passwd ; then echo tem ; fi $ grep -qs root /etc/passwd $ echo $? $ grep -qs roiiiiiiot /etc/passwd $ echo $? $ cp $ echo $? $ exit abnc $ cp 2>/dev/null $ echo $? $ ls /dev/null
O [[ para fazer testes
$ if [ 1 -gt 5 ]; then echo é menor ; fi $ if [ 8 -gt 5 ]; then echo é maior ; fi $ if [[ 8 -gt 5 ]]; then echo é maior ; fi $ if [[ 8 5 ]]; then echo é maior ; fi
Os operadores lógicos AND && e OR ||
$ cp 2>/dev/null ; echo $? $ cp 2>/dev/null && echo OK $ ls 2>/dev/null && echo OK $ ls >/dev/null 2>&1 && echo OK $ ls >/dev/null 2>&1 || echo OK $ cp 2>/dev/null || echo OK $ cp 2>/dev/null || echo OK && echo NOK $ echo && echo OK || echo NOK $ echo && cp 2>/dev/null || echo NOK $ false && cp 2>/dev/null || echo NOK $ false && cp || echo NOK $ true && cp || echo NOK $ false && cp || echo NOK $ false && cp || echo NOK && echo OKDENOVO $ false && { cp || echo NOK && echo OKDENOVO ; } $ true && { cp || echo NOK && echo OKDENOVO ; }
Checagem de parâmetros da linha de comando ($1)
$ test -z "$1" || { echo uso: blabla ; exit 1 ; } $ [ "$1" ] || { echo uso: blabla ; exit 1 ; } $ [ "$1" ] || { echo uso: blabla ; echo exit 1 ; } $ [ $1 ] || { echo uso: blabla ; echo exit 1 ; } $ [ $1 = '--help' ] || { echo uso: blabla ; echo exit 1 ; } $ [ "$1" = '--help' ] || { echo uso: blabla ; echo exit 1 ; } $ [ = '--help' ] || { echo uso: blabla ; echo exit 1 ; }
Como passar parâmetros vazios
$ vi teste.sh $ ./teste.sh $ ./teste.sh "" $ ./teste.sh "" dois $ ./teste.sh "" "" dois
As ferramentas: cut
$ cat /etc/passwd | cut -d: -f5 $ cat /etc/passwd | cut -d: -f5,2 $ cat /etc/passwd | cut -d: -f5,2,1 $ cat /etc/passwd | cut -d: -f5- $ cat /etc/passwd | cut -d: -f5-6 $ cat /etc/passwd | cut -d: -f5-7 $ cat /etc/passwd | cut -c 1-10 $ cat /etc/passwd | cut -c 10-
As ferramentas: awk
$ cat /etc/passwd | awk '{print $3}' $ cat /etc/passwd | awk '{print $3}' $ cat /etc/passwd | awk '{print $2}' $ cat /etc/passwd | awk '{print $1}' $ cat /etc/passwd | awk '{print $2}' $ cat /etc/passwd | awk -F: '{print $2}' $ cat /etc/fstab $ cat /etc/fstab | cut -d" " -f4 $ cat /etc/fstab | awk '{print $4}'
As ferramentas: tr
$ a="asd asd k ioioio" $ echo $a $ echo "$a" $ echo "$a" | tr -s ' ' $ echo aaaaabbbb | tr -s a $ echo aaaaabbbb | tr -s ab $ echo aaaaabbbb | tr a-z A-Z $ echo aaaaabbbb | tr abcdef ABCDEF $ echo aaaaabbbb | tr abcdef XVDGFFG
As ferramentas: sort
$ cat /etc/passwd $ cat /etc/passwd | sort $ cat /etc/passwd | sort -r
As ferramentas: rev, tac
$ cat /etc/passwd | rev $ echo abcde | rev $ echo cat | rev $ tac /etc/passwd $ tac /etc/passwd| rev
As ferramentas: sort, uniq
$ vi txt $ cat txt | sort $ cat txt | sort | uniq $ cat txt | uniq $ cat txt | sort -u $ cat txt | sort | uniq
As ferramentas: wc
$ cat /etc/passwd | wc $ cat /etc/passwd | wc -w $ cat /etc/passwd | wc -l $ cat /etc/passwd | wc -c
As ferramentas: cat, paste
$ vi txt2 $ cat txt txt2 $ paste txt txt2 $ paste -s txt txt2
As ferramentas: tee
$ echo abc $ echo abc | sed 's/a/./' $ echo abc | tee a | sed 's/a/./' $ cat a
As ferramentas: head, tail
$ head /etc/passwd $ head -2 /etc/passwd $ tail -2 /etc/passwd $ tail /etc/passwd
As ferramentas: seq
$ for i in 1 2 3 4 5 5 6 7 8 9 10; do echo $i-- ; done $ for i in 1 2 3 4 5 5 6 abd hjerer jrtj 8 9 10; do echo $i-- ; done $ for i in $(seq 10); do echo $i-- ; done $ seq 10 $ seq 2 $ seq 2 5 $ seq 5 2 $ seq 4 8 50
As ferramentas: printf
$ printf "%s" bla $ printf "%s\n" bla $ printf "%10s\n" bla $ printf "%-10s\n" bla $ printf "%10s----\n" bla $ printf "%-10s----\n" bla $ printf "%10s----\n" blaasdasdasdasd $ printf "%d" 5 $ printf "%d\n" 5 $ printf "%4d\n" 5 $ printf "%4d\n" 5 | sed 's/ /0/g' $ printf "%.4d\n" 5 $ printf "%4.2f\n" 5
As ferramentas: grep
$ cat /etc/passwd $ cat /etc/passwd | grep root $ cat /etc/passwd | grep -i root $ cat /etc/passwd | grep -i ROOT $ cp $ echo $LANG $ cat /etc/passwd | grep -w root $ cat /etc/passwd | grep -w roo $ cat /etc/passwd | grep -x roo $ cat /etc/passwd | grep -l roo $ grep -l roo /etc/passwd $ grep -v roo /etc/passwd $ grep -v root /etc/passwd $ VAR=root $ grep -i $VAR /etc/passwd $ grep g /etc/passwd $ grep g\$ /etc/passwd $ fgrep g\$ /etc/passwd $ fgrep g /etc/passwd $ cd /bin $ l grep egrep fgrep
As ferramentas: find
$ find . -type f $ find . -type d $ find . -type l $ ln -s a z $ find . -type l $ find . -type f $ find . -type f -exec echo rm -f {} \; $ find . -type f -ok echo rm -f {} \; $ find . -type f | while read BOZO; do echo $BOZO; done $ cat /etc/passwd | while read BOZO; do echo $BOZO; done $ cat /etc/passwd | while read BOZO; do echo {$BOZO}; done $ cat /etc/passwd | while read BOZO; do echo $BOZO | grep -qs root && echo $BOZO; done $ find . -type f -exec echo rm -f {}\;
As ferramentas: date
$ date $ date +'%y %m %d' $ date +'%Y %m %d' $ date --help $ date +'%Y-%m-%d' $ date +'%Y-%m-%d %H:%M' $ date +'hoje é %Y-%m-%d %H:%M ... ' $ date +'%s' $ date +'%s' $ date +'%s'
As ferramentas: diff, vi -d
$ cat txt txt2 $ diff txt txt2 $ vi txt2 $ cp txt txt3 $ vi txt3 $ diff txt txt3 $ diff -u txt txt3 $ diff -u txt txt3 | vi - $ vi txt3 $ diff -u txt txt3 | vi - $ vi txt3 $ diff -u txt txt3 | vi - $ vi txt3 $ diff -u txt txt3 | vi - $ vi -d txt txt3
Funções separadas em uma biblioteca
$ cds $ vi functions $ ./functions $ source functions $ . functions $ vi inet