Documente Academic
Documente Profesional
Documente Cultură
Salviano A. Leo
21/12/2013
Sumrio
1 Introduo
2 O comando find
2.1 Parmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2
. . .
. . .
. . .
. . .
find
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
10
10
11
11
12
14
15
15
15
16
18
19
20
4 O comando xargs
21
24
26
27
28
Introduo
Neste trabalho, apresentaremos o comando find e alguns exemplos de seu uso, pois uma das
tarefas mais corriqueiras em um sistema operacional a de encontrar arquivos que possuam
algum tipo de restrio, como por exemplo arquivos cujos(as):
nomes que contenham algum tipo de sequncia de caracteres;
1
Ambos servem para pesquisar arquivos no sistema de diretrios do Linux. Contudo existem
algumas diferenas que precisam ser salientadas.
O comando find utilizado para procurar por arquivos na rvore de diretrios. Isto ,
ele tenta localizar o que solicitamos dentro do local que indicamos checando os subdiretrios
tambm.
O comando find
2.1
Parmetros
expresso Define os critrios a serem usados na pesquisa. Essa pode ser uma combinao
entre vrios tipos de procura;
ao Define a ao que ser executada nos arquivos que atenderem aos critrios da pesquisa
definidos em expresso.
Os principais critrios de pesquisa definidos por expresso so:
-name nome Procura arquivos que tenham o nome especificado. Aqui podem ser usados
metacaracteres ou caracteres curingas, porm estes caracteres devero estar entre aspas,
apstrofos ou imediatamente precedidos por uma contrabarra \, para que o shell no
interprete esse caractere.
-iname Idntico opo -name. Porm neste caso, ignora maisculas e minsculas. Deve ser
usada quando no sabemos se o nome do arquivo possui letras maisculas.
-user usurio Procura arquivos que tenham usurio como dono;
-group grupo Procura arquivos que tenham grupo como grupo dono;
-type c Procura por arquivos que tenham o tipo c, correspondente letra do tipo do arquivo.
Os tipos aceitos esto na tabela a seguir:
Valores de c
b
c
d
p
f
l
s
D
-size n[bckw ] Procura por arquivos que usam mais (+n) de n unidades de espao ou a
menos (-n) de n unidades de espao.
Unidade
b
c
k
w
Valor
Bloco de 512 bytes (valor default)
Caracteres
Kilobytes (1024 bytes)
Palavras (2 bytes)
Procura por arquivos que foram acessados h mais (+d) de d
-atime d
dias ou a menos (-d) de d dias;
Procura por arquivos cujo status mudou h mais (+d) de d
-ctime d
dias ou a menos (-d) de d dias;
Procura por arquivos cujos dados foram modificados h mais
-mtime d
(+d) de d dias ou a menos (-d) de d dias;
Para usar mais de um critrio de pesquisa, faa: expresso1 expresso2 ou expresso1 -a
expresso2 para atender aos critrios especificados por expresso1 e expresso2; expresso1
-o expresso2 para atender aos critrios especificados por expresso1 ou expresso2.
As principais aes definidas para ao so:
3
-print Esta opo faz com que os arquivos encontrados sejam exibidos na tela. Esta a opo
padro (default) no Linux.
-exec cmd {} \; Executa o comando cmd. O escopo de comando considerado encerrado
quando um ponto-e-vrgula (;) encontrado. A cadeia {} substituda pelo nome de
cada arquivo que satisfaz ao critrio de pesquisa e a linha assim formada executada.
Assim como foi dito para a opo name, o ponto-e-vrgula (;) deve ser precedido por uma
contrabarra (\), ou deve estar entre aspas ou apstrofos;
-ok cmd {} \; O mesmo que o anterior porm pergunta se pode executar a instruo cmd
sobre cada arquivo que atende ao critrio de pesquisa;
-printf formato Permite que se escolha os campos que sero listados e formata a sada de
acordo com o especificado em formato.
Com a opo printf possvel formatar a sada do comando find e especificar os dados
desejados. A formatao do printf muito semelhante do mesmo comando na linguagem C e interpreta caracteres de formatao precedidos por um smbolo de percentual
(%). Vejamos seus efeitos sobre a formatao:
Caractere
%f
%F
%g
%G
%h
%i
%k
%l
%m
%p
%s
%u
%U
Significado
Nome do arquivo (baseneme, caminho completo no aparece)
Indica a qual tipo de file system o arquivo pertence
Grupo ao qual o arquivo pertence
Grupo ao qual o arquivo pertence (GID- Numrico)
Caminho completo do arquivo (dirname, tudo menos o nome)
Nmero do inode do arquivo (em decimal)
Tamanho do arquivo em Kbytes
Destino do link simblico
Permisso do arquivo (em octal)
Nome completo do arquivo (dirname+basename)
Tamanho do arquivo
Nome de usurio (username) do dono do arquivo
Nmero do usurio (UID) do dono do arquivo
Significado
Data do ltimo acesso
Data de criao
Data de alterao
Nesse exemplo, o %p foi o responsvel por colocar os nomes dos arquivos. Caso fosse
omitido, somente as datas seriam listadas.
Observe ainda que ao final foi colocado um /n. Sem ele no haveria salto de linha e a
listagem anterior seria uma grande tripa.
Essas datas tambm podem ser formatadas, para isso basta passar as letras da tabela
anterior para maisculas (%A, %C e %T) e usar um dos formatadores das duas tabelas
a seguir:
Tabela de formatao de tempo:
Caractere
H
I
k
l
M
p
r
S
T
Z
Significado
Hora (00..23)
Hora (01..12)
Hora (0..23)
Hora (1..12)
Minuto (00..59)
AM or PM
Horrio de 12 horas (hh:mm:ss) seguido de AM ou PM
Segundos (00 ... 61)
Horrio de 24-horas (hh:mm:ss)
Fuso horrio (na Cidade Maravilhosa BRST)
Significado
Dia da semana abreviado (Dom...Sab)
Dia da semana por extenso (Domingo...Sbado)
Nome do ms abreviado (Jan...Dez)
Dia do ms por extenso (Janeiro...Dezembro)
Data e hora completa (Fri Dec 23 15:21:41 2005)
Dia do ms (01...31)
Data no formato mm/dd/aa
Idntico a b
Dia seqencial do ano (001366)
Ms (01...12)
Semana seqencial do ano. Domingo como 1 dia da semana (00...53)
Dia seqencial da semana (0..6)
Semana seqencial do ano. Segunda-feira como 1 dia da semana (00...53)
Representao da data no formato do pas (definido por $LC_ALL)
Ano com 2 dgitos (00...99)
Ano com 4 dgitos
Para melhorar a situao, vejamos uns exemplos; porm, vejamos primeiro quais so os
arquivos do diretrio corrente que comeam por .b:
> ls - la . b *
-rw - - - - - - -rw -r - -r - -rw -r - -r - -rw -r - -r - -
1
1
1
1
d276707
d276707
d276707
d276707
ssup
ssup
ssup
ssup
21419
24
194
142
No exemplo que acabamos de ver, o \t foi substitudo por um <TAB> na sada de forma
a tornar a listagem mais legvel. Para listar os mesmos arquivos classificados por data e
hora da ltima alterao:
> 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
Iniciaremos com uma srie de exemplos mais simples, para ir gradativamente aumentando a
complexidade dos exemplos de uso deste comando.
1) Buscando o arquivo Arquivo-X na pasta atual e em outras pastas:
Na pasta atual:
> find . - name Arquivo - X
2) Buscando apenas arquivos, dentro do diretrio atual, que no tenham a extenso .txt:
> find . \!
name
*. txt
no fim do nome
> find . - name " * Arq "
Para a opo -type, o d significa uma pasta (diretrio) regular, o f significa um arquivo regular enquanto o l significa um link simblico. Para as outras possibilidades,
consulte o manual do comando find.
5) Buscando arquivos ou pastas dos usurios do sistema que se encontram no /home, com uma
determinada permisso, atribuda pelo comando chmod:
Arquivos com a permisso dada por: chmod 777
> find / home - type f - perm 777
6) Buscando arquivos dos usurios do sistema que se encontram no /home com um determinado
tamanho:
Com mais de 500 kb:
> find / home - type f - size +500 k
O que faz: Procura no diretrio home (find /home) arquivos (-type f) com permisso 777
(-perm 777) que pertenam ao usurio root (-user root) e executa chmod 644 em cada
arquivo (representado por {}).
O fim do comando -exec deve ser explicitado, pois voc pode usar expresses tanto antes
de {} (isto chamado de lista) quanto depois.
Coloca-se o caracter \, assim o shell no interepretar o caractere seguinte, que o ;, que
indica o final da instruo -exec.
> find / home - type f - ctime +10 && -60 - exec
mv {} / tmp / teste \;
O que faz: Procura arquivos no diretrio home com permisso 777 (find /home -type f -perm 777)
e move para a pasta /tmp/teste (-exec mv {} /temp/teste \;).
Para incrementar as buscas interessante saber como trabalhar com expresses regulares,
assunto este que ser tratado em outro artigo.
Darei alguns exemplos da utilidade de expresses regulares, mas no se preocupe em entender, pois um assunto para outro artigo.
O recurso -iname usado quando voc no quer diferir maiscula de minscula, isto ,
retira o modo case sensitive do termo a ser buscado. Ao usar a expresso seguinte entre
aspas simples, voc estar usando expresses regulares ao invs de um nome especfico, ou
seja, um -iname/-name mais elaborado.
Exemplo 1 :
> find / home - iname " .* jpg "
Busca todos os arquivos que tenham qualquer carcter (representado por .) em qualquer
quantidade (representado por *) e que termine por jpg.
Exemplo 2:
> find / home - iname " DSC .*\. jpg "
Busca por arquivos que comecem por DSC e que contenham qualquer coisa em qualquer
quantidade at encontrar um .jpg.
Para listar na tela (-print) todos os arquivos, a partir do diretrio corrente, terminados
por .sh, faa:
> find . - name \*. sh
./ undelete . sh
./ ntod . sh
./ dton . sh
./ graph . sh
./ tstsh / cotafs . sh
./ tstsh / data . sh
./ tstsh / velha . sh
./ tstsh / charascii . sh
Preciso abrir espao em um determinado file system com muita urgncia, ento 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 fao:
> find . type f size +1000000 c atime +60 exec rm {} \;
Neste exemplo devemos realar alm das contrabarras (\) antes dos asteriscos (*), o uso do
o para uma ou outra extenso e que o diretrio inicial era o raiz (/); assim sendo, esta pesquisa
deu-se no disco inteiro (o que frequentemente bastante demorado).
3.1
3.2
O comando find extremamente poderoso e flexvel para descobrir arquivos que atendem a
determinadas especificaes.
Por exemplo, suponhamos que queiramos descobrir todos os arquivos que no possuem
dono em nosso sistema. Esta situao extremamente comum, visto que usurios so criados e
apagados diariamente e ficam vagando pelo sistema e podem eventualmente vir a comprometer
a segurana. O comando
> find / - nouser - print
10
ir gerar uma listagem com todos os arquivos do sistema que no pertencem a ningum.
Caso queiramos simplesmente apagar estes arquivos (no recomendvel!!!) basta redirecionar a sada deste comando para o comando xargs, da seguinte forma:
> find / - nouser - print | xargs rm
3.3
Muitas vezes temos arquivos armazenados em diversas pastas, e quando precisamos realizar
uma limpeza destes arquivos, existe a grande dificuldade de localizar primeiramente onde esto
e depois pasta a pasta realizar a limpeza.
Nesta semana precisei liberar espao em meu servidor, para isso resolvi limpar os backups
mais antigos do mysql que fao usando o script automysqlbackup.sh, a comea o meu problema.
O comando rm -R no consegue apagar arquivos por expresso regular, ou seja:
rm -R "*2009*" retorna rm: cannot remove *2009*: No such file or directory.
Procurando no google por solues encontrei apenas scripts para fazer esta tarefa, sendo
que muitos deles listavam arquivos usando o comando find.
Tentando criar minha prpria soluo, lendo o man do Find, descobri que o prprio comando
find tem uma ao de deleo que poderia servir nestes casos, o comando :
> find [ pasta raiz ] - name " [ a express o ] " - delete
Com isto todos os arquivos dos subdiretrios abaixo de /backups que continham 2009 em
seu nome foram deletados.
3.4
O comando find tambm possui a opo -empty a qual encontra arquivos ou diretrios vazios.
Para encontrar e apagar todos os diretrios vazios que estejam abaixo da estrutura /home/salviano/tmp
use o seguinte comando:
> find / home / salviano / tmp - empty - type d - delete
11
Para encontrar e apagar todos os arquivos vazios que estejam abaixo da estrutura /home/salviano/tmp
use o seguinte comando:
> find / home / salviano / tmp - empty - type f - delete
> find / home / salviano / tmp - type d - empty - print0 | xargs -0 -I {} / bin /rmdir " {} "
3.5
12
E por a vai, dezenas de linhas deste tipo. Rejeio em massa, um problema grave para
quem tem auto estima baixa :-)
Se eu puder ignorar as mensagens de erro com segurana, basta redirecion-las para o buraco
negro de sistemas *nix, o dispositivo /dev/null:
> find / - name password \* 2 > / dev / null
/ var / lib / pam / password
/ var / cache / debconf / passwords . dat
/ usr / share / ri /1.8/ system / CGI / HtmlExtension / password_field - i . yaml
/ usr / share / ri /1.8/ system / URI / Generic / password - i . yaml
/ usr / share / ri /1.8/ system / URI / Generic / password %3 d - i . yaml
/ usr / share / pixmaps / password . png
/ usr / lib / pppd /2.4.4/ passwordfd . so
O 2> representa a sada padro para erros (standard error output stream). De forma mais
simples, a sada padro para erros, tambm conhecida por stderr, o local para onde a maior
parte dos comandos executados enviam suas mensagens de erro. As mensagens normais so
enviadas para a sada padro (stdout), representada pelo nmero 1.
Mas vejamos uma outra situao. Executemos o mesmo comando, mas redirecionando a
sada para um arquivo:
> find / - name password \* > saida . txt
find : '/ lost + found ': Permiss o negada
find : '/ etc / ppp / peers ': Permiss o negada
find : '/ etc / cups / ssl ': Permiss o negada
find : '/ etc / chatscripts ': Permiss o negada
find : '/ etc / ssl / private ': Permiss o negada
find : '/ var / lib / mysql ': Permiss o negada
A sada padro, stdout, foi direcionada para o arquivo saida.txt, mas os erros (stderr),
continuaram sendo enviados para a tela. A diferena mais significativa que o arquivo contm
o que me interessa. Mesmo assim, meio trabalhoso, no?
Posso fazer melhor. Eu posso redirecionar a sada padro para um arquivo e os erros para
outro:
> find / - name password \* 2 > / tmp / erros . txt 1 > / tmp / saida . txt
13
Bastante til. Por exemplo, ao rodar um shell script via cron do sistema, voc pode querer
que os erros lhe sejam enviados por email, para ver se tudo correu bem. s fazer um teste e
ver se o arquivo de erros tem contedo. Se tiver, envie o arquivo para voc mesmo para que a
situao possa ser analisada e as aes apropriadas sejam tomadas.
3.6
O comando find extremamente til para procurar arquivos que restritos a um critrio particular. O find pode procurar arquivos que foram modificados nos ltimos N dias, arquivos
maiores que um tamanho especifico ou arquivos que pertenam a um userid que no est
definido no seu arquivo /etc/passwd, por exemplo, so exemplos de situaes fceis de serem
resolvidas pelo comando find (e muito uteis, tambm). Tambm pode-se procurar arquivos
de tipos especficos - como diretrios, links simblicos ou arquivos normais - ou arquivos mais
novos que um outro arquivo.
Pode-se procurar arquivos baseando-se em suas permisses (por exemplo, todos os arquivos
que possuem o bit setuid). Pode-se restringir comandos find a um diretrio especifico ou a
um file-systems.
O que pode no ser to bvio quanto a construo do comando find apropriado para fazer
o servio de vasculhar pelo que se procura como construir um comando que ir fazer o que se
quer com os arquivos, uma vez que os tenha encontrado.
- print e - ls
Os dois comandos mais comuns usados com find so, no surpreendentemente, o -print e
o -ls. A opo -print imprime o nome do arquivo do ponto de vista do diretrio corrente (ex.
/export/home/teste/tralha.txt ou somente ./teste/tralha.txt se a procura foi iniciada
a partir do /export/home). A opo -ls proporciona o mesmo tipo de informao que se iria
ver se visualizasse os arquivos atravs do comando ls -li.
- exec
A opo -exec eh indubitavelmente a prxima opo mais popular e usada para especificar
o que o find ir fazer com os arquivos que ele encontrar. Quando usamos a opo -exec, o
nome de cada arquivo encontrado pelo find representado no comando find pela sequencia
de caracteres "{}"(sem as aspas ;-] ). O comando para imprimir o nmero de linhas em cada
um dos arquivos encontrados pelo find ir se parecer com isso:
root > find . - type f - exec wc -l {} \;
A sequencia marca o fim do comando e, executando-o, poderia-se ter, como resultado, algo
como:
74 ./030701 _log . txt
12 ./ testfile1
6 ./ testfile2
5 ./ ex
O -print neste comando eh colocado no final para que os arquivos mostrados sejam somente
os que passaram pelo teste do grep.
3.6.1
Para modificar o contedo de arquivos que so localizados pelo find, pode-se usar o sed ou
pode-se usar ainda um comando Perl como este que executado em todos os arquivos HTML
no diretrio corrente e subdiretrios para alterar uma URL para outra:
> find . - type f - name " *\. html " - exec perl -i -p -e \
's / www . antes . org / www . depois . com / g ; ' {} \;
Se frequentemente tm-se que mudar links em um website muito grande, um comando como
esse certamente ira livrar muito tempo (e trabalho). Para repassar este comando a algum que
no ir gostar de lembrar do comando find, pode-se coloca-lo num script como esse:
# !/ bin / bash
if [ $ # != 2 ]; then
echo " usage $0 < antes > < depois > "
exit
else
ANTES = $1
DEPOIS = $2
fi
find . - type f - name " *\. html " - exec perl -i -p -e \
" s / $ANTES / $DEPOIS / g ; " {} \;
3.6.2
Neste loop o nome do seu arquivo associado ao $i. Este comando trabalha com shells da
familia Bourne Shell (sh, ksh, bash e outros).
Muito trabalho pode ser realizado com uma combinao inteligente do comando find.
15
3.7
Para descobrir links simblicos que apontam para arquivos que no existem mais, use o comando
find:
> find . - type l - follow 2 >/ dev / stdout | cut - d : -f 2 | xargs rm -f
To display a list of the broken links, replacing ${directory} with the desired root directory
Edit
> find -L / path / to / search - type l
> find / path / to / search - xtype l
as explained at http://ynform.org/w/Pub/UnixSymbolicLink
for f in $ ( find / path / to / search - type l ) ; do if [ ! -e " $f " ]; then echo "$f " ; fi ; done
To display a list of the broken links, with where they link to Edit
> find - xtype l - exec ls -l {} \;
> find / usr / local / bin - type l | while read f ; do if [ ! -e " $f " ]; then ls -l " $f " ; fi ; done
all one line, if there are broken links it will display them with ls -l
To REMOVE the broken links Edit
> find / path / to / search - xtype l - delete
> find -L / path / to / search - type l - delete
> find / path / do / search - type l | while read f ; do if [ ! -e " $f " ]; then rm-f " $f " ; fi ; done
None of these methods will detect cyclic links. To detect cyclic symbolic links use
> find / path / to / search - type l -a ! \
\( - xtype b -o - xtype c -o - xtype d -o - xtype p -o - xtype f -o - xtype s -o - xtype l \) 2 >/ dev / null
16
s vezes por causa de algum cp descuidado, copia-se apenas os arquivos e ficam faltando
os links simblicos. ou ainda, como saber quais so os links simblicos de um determinado
diretrio e para onde eles apontam. a resposta mais simples do que se imagina: find.
Assim como -type d" procura apenas por diretrios, o find possui a opo -type l" para
procurar links simblicos. ento j sabemos como encontrar quais so os links. resta saber para
onde eles apontam.
o find do GNU possui a opo -printf, que possui vrios
Caractere
%f
%F
%g
%G
%h
%i
%k
%l
%m
%p
%s
%u
%U
Significado
Nome do arquivo (baseneme, caminho completo no aparece)
Indica a qual tipo de file system o arquivo pertence
Grupo ao qual o arquivo pertence
Grupo ao qual o arquivo pertence (GID- Numrico)
Caminho completo do arquivo (dirname, tudo menos o nome)
Nmero do inode do arquivo (em decimal)
Tamanho do arquivo em Kbytes
Destino do link simblico
Permisso do arquivo (em octal)
Nome completo do arquivo (dirname+basename)
Tamanho do arquivo
Nome de usurio (username) do dono do arquivo
Nmero do usurio (UID) do dono do arquivo
abusando s um pouquinho dessa poderosa possibilidade, podemos "salvar"o estado atual dos
links simblicos, gerando um script para reconstru-los caso necessrio:
# !/ bin / sh
# ln - save - gera um script de reconstru o de symlinks
echo ' OLDPWD = $PWD '
17
exemplo de uso:
> cd / etc ; ln - save > / tmp / reconstroi - links . sh
> cd / etc - novo ; sh / tmp / reconstroi - links . sh
3.8
Mais do find
cd / tmp
# va para uma area traquila
mkdir tst ; cd tst # crie uma regi o limpa e entre nela
touch a b c d
# crie quatro arquivos
ls
# veja se est o l
b c d
# busque somente os diretorios " b " e " d " e inclua no seu archive . cpio
find - name " a " -o - name " c " -o print | cpio -o > archive . cpio
Por partes:
O find busca os nomes a ou c caso contrario, IMPRIME na sada e o cpio faz o resto.
A dica aqui buscar justamente o que se quer evitar dentro do arquivo. O find gera as
listas baseada no print e no no que foi encontrado, como o senso comum nos levaria a
crer.
No lugar do a e c, use os nomes de arquivo e de diretrios que voc deseje encontrar de
fato
Se usarmos nomes de diretrios e a clusula -prune (logo aps o nome do diretrio),
eliminamos o diretrio e todo o seu contedo (da lista!).
# == Ex 2 - ( mais complexo ) :==
> cd / tmp / tst
> ls
a b c d
18
> # busque somente os diretorios " b " e " d " e exclua a pasta " e " , existenteno subdir " pasta "
> find - name " a " \
-o - name " c " \
-o - name " e " - prune \
-o - print | cpio -o > archive . cpio
> cpio -t < archive . cpio # liste o conteudo do novo archive
.
d
b
pasta
pasta / f
archive . cpio
1 block
Perceba que a pasta e (e todo o contedo se houvesse ) ficou de fora assim como os arquivos a
e c.
3.9
Para alterar recursivamente a propriedade de uma rvore de diretrios para uma determinada
pessoa e grupo, usamos o comando chown:
> chown -R sleao : sleao sleao
Com o comando acima, pretendo alterar apenas a propriedade dos diretrios a partir de um
determinado ponto. Se existir algum diretrio com um nome que contenha espaos em branco,
teremos problema.
> find
chown :
chown :
chown :
chown :
chown :
chown :
chown :
chown :
19
chown : imposs vel acessar `de ': Arquivo ou diret rio n o encontrado
chown : imposs vel acessar ` Faxina ': Arquivo ou diret rio n o encontrado
No exemplo acima eu criei dois diretrios com espaos em branco com o nome: Salviano de
Araujo Leo Dia de Faxina. O comando xargs forneceu como entrada ao comando chown, as
partes individuais dos nomes, levando em considerao o espao em branco como delimitador
do nome.
Para resolver este problema, precisamos informar ao comando xargs que o delimitador
outro:
> find . - type d - print0 | xargs -0 chown -R sleao
A opo -print0 termina os nomes dos arquivos com um zero, de forma que os nomes de
arquivos com espaos em branco sejam corretamente tratados. Da mesma forma, no comando
xargs o argumento -0 indica que o separador do nome dos arquivos o zero e no o espao em
branco.
O argumento -print opcional. Verses antigas de sistemas Unix exigiam que fosse especificado no comando find. As verses modernas de sistemas GNU/Linux e FreeBSD no exigem
sua especificao, a no ser em casos como acima, em que atribuimos um valor diferente do
padro ao delimitador do nome de arquivos.
3.10
Considere que aps uma contagem de arquivos e diretrios em uma pasta de uso pessoal, o
usurio misterx encontre:
Diretrios vazios
> find . - type d - empty | wc
1154
1234
65924
Arquivos vazios
> find . - type f - empty | wc
1001
1065
85839
troni :[/ home / misterx ]
Assustador, no? 1154 diretrios e 1001 arquivos vazios. A maioria destes arquivos so criados automaticamente, pelos programas que usamos normalmente. Arquivos e diretrios vazios
podem ter uma funo, principalmente em se tratando de arquivos do sistema operacional. No
caso de arquivos do diretrio home, este raramente o caso e com raras excees podem ser
removidos.
Para remover estes arquivos, basta completar o comando find com algumas diretivas adicionais.
> find / home / misterx - type d - empty - delete
> find / home / misterx - type f - empty - delete
20
2) Uma verso segura para remover diretrios vazios porm um pouco mais lenta devido ao
-exec
> find / home / misterx - type d - empty - print0 - exec rmdir -v " {} " \;
4) Uma verso segura para remover arquivos vazios porm um pouco mais lenta devido ao
-exec
> find / home / misterx - type f - empty - print0 - exec rmdir -v " {} " \;
O comando xargs
Existe um comando, cuja funo primordial construir listas de parmetros e pass-la para
a execuo de outros programas ou instrues. Este comando o xargs e deve ser usado da
seguinte maneira:
xargs [ comando [ argumento inicial ]]
Caso o comando, que pode ser inclusive um script Shell, seja omitido, ser usado por default
o echo.
O xargs combina o argumento inicial com os argumentos recebidos da entrada padro, de
forma a executar o comando especificado uma ou mais vezes.
Exemplo:
Vamos produrar em todos os arquivos abaixo de um determinado diretrio uma cadeia de
caracteres usando o comando find com a opo -type f para pesquisar somente os arquivos
regulares, desprezando diretrios, arquivos especiais, arquivos de ligaes, etc, e vamos torn-la
21
mais genrica recebendo o nome do diretrio inicial e a cadeia a ser pesquisada como parmetros.
Para isso fazemos:
> 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 execuo deste script procuramos, a partir do diretrio definido na varivel $1, todos os
arquivos que continham a cadeia definida na varivel $2.
Exatamente a mesma coisa poderia ser feito se a linha do programa fosse a seguinte:
> find $1 - type f - exec grep -l " $2 " {} \;
Quase estaria certo, o problema que desta forma voc removeria no s os arquivos do
cara no diretrio corrente, mas tambm de todos os outros subdiretrios "pendurados"neste.
Vejamos ento como fazer:
> ls -l | grep " cara " | cut -c55 - | xargs rm
Desta forma, o grep selecionou os arquivos que continham a cadeia cara no diretrio corrente
listado pelo ls -l. O comando cut pegou somente o nome dos arquivos, passando-os para a
remoo pelo rm usando o comando xargs como ponte.
O xargs tambm uma excelente ferramenta de criao de one-liners (scripts de somente
uma linha). Veja este para listar todos os donos de arquivos (inclusive seus links) "pendurados"no diretrio /bin e seus subdiretrios.
22
Muitas vezes o /bin um link (se no me engano, no Solaris o ) e a opo -follows obriga
o find a seguir o link. O comando xargs alimenta o ls -al e a seqncia de comandos seguinte
para pegar somente o 3campo (dono) e classific-lo devolvendo somente uma vez cada dono
(opo -u do comando sort).
Voc pode usar as opes do xargs para construir comandos extremamente poderosos. Para
exemplificar isso e comear a entender as principais opes desta instruo, vamos supor que
temos que remover todos as arquivos com extenso .txt sob o diretrio corrente e apresentar os
seus nomes na tela. Veja o que podemos fazer:
> find . - type f - name " *. txt " | \
xargs -i bash -c " echo removendo {}; rm {} "
A opo -i do xargs troca pares de chaves ({}) pela cadeia que est recebendo pelo pipe
(|). Ento neste caso as chaves ({}) sero trocadas pelos nomes dos arquivos que satifaam ao
comando find.
Olha s a brincadeira que vamos fazer com o xargs:
> 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 sada do ls para o arquivo usando o xargs, comprovamos o que foi
dito anteriormente, isto , o xargs manda tudo que possvel (o suficiente para no gerar um
estouro de pilha) de uma s vez. Em seguida, usamos a opo -n 1 para listar um por vez. S
para dar certeza veja o exemplo a seguir, quando listaremos dois em cada linha:
> 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 (|), da seguinte forma:
> xargs -n 2 < arq . ls
Outra opo legal do xargs a -p, na qual o xargs pergunta se voc realmente deseja
executar o comando. Digamos que em um diretrio voc tenha arquivo com a extenso .bug e
.ok, os .bug esto com problemas que aps corrigidos so salvos como .ok. D uma olhadinha
na listagem deste diretrio:
> ls dir
arq1 . bug
arq1 . ok
arq2 . bug
23
arq2 . ok
...
arq9 . bug
arq9 . ok
Para finalizar, o xargs tambm tem a opo -t, onde vai mostrando as instrues que
montou antes de execut-las. Gosto muito desta opo para ajudar a depurar o comando que
foi montado.
Ento podemos resumir o comando de acordo com a tabela a seguir:
Opo
-i
-nNum
-lNum
-p
-t
Ao
Substitui o par de chaves ({}) pelas cadeias recebidas
Manda o mximo de parmetros recebidos, at o mximo de Num para o comando a ser execut
Manda o mximo de linhas recebidas, at o mximo de Num para o comando a ser executado
Mostra a linha de comando montada e pergunta se deseja execut-la
Mostra a linha de comando montada antes de execut-la
A diferena que no primeiro find o comando ls executado uma vez para cada arquivo
encontrado. Se forem encontrados 1000 arquivos o comando ls ser executado 1000 vezes.
J no segundo exemplo, com a sada do find redirecionada para o comando xargs, o
comando ls ser executado sobre um grupo de arquivos de cada vez e no uma vez para cada
arquivo. O que ir determinar o nmero de vezes que o comando xargs executar o comando
ls justamente o tamanho da linha de comandos. O comando xargs ir dividir a sada gerada
pelo comando find em blocos compatveis com a capacidade do sistema de maneira a que no
ocorra um erro quando da execuo, em nosso caso, do comando ls.
Em outras palavras, suponhamos que o comando find descubra 2000 arquivos sobre os quais
o comando xargs dever executar o comando ls. O limite mximo de arquivo sobre os quais o
comando ls pode atuar de 500. O comando xargs automaticamente realizar a diviso desta
entrada em quatro blocos de 500 arquivos.
Concluindo, o comando xargs bem mais eficiente do que a diretiva -exec do comando
find, por exigir menos recursos computacionais para executar a mesma tarefa. uma vez sobre
todos os arquivos encontrados.
Pode ser que voc j tenha tentado dar um comando usando o asterisco * no bash e tenha
obtido este erro:
24
Nesse caso, o comando poderia ser um rm, ou um cp, ou qualquer outro. Por exemplo:
> rm -f *
bash : / bin / rm : Argument list too long
>
Quem imprimiu esse erro no foi o comando (o rm, no exemplo), mas o bash, que responsvel por expandir o wildcard *, substituindo-o pela lista de arquivos no diretrio. Em sistemas
UNIX, h um limite fixo de memria reservado para o ambiente e lista de parmetros de um
comando. No caso do meu servidor Linux, esse limite 128K, mas isso varia de sistema para
sistema. Voc pode descobrir no seu sistema usando o comando getconf. Veja:
> getconf ARG_MAX
131072
Agora, ao que interessa. Como fazer para remover os arquivos do meu exemplo acima?
Existem diversas sadas, variando a eficincia dependendo de qual o seu comando, na verdade.
Mas vamos ver o rm, pois o exemplo dele pode ser aplicado a outros, como por exemplo o cp,
ou o mv.
Se voc puder eliminar o diretrio inteiro no qual esto os arquivos, no h problemas:
> rm - rf teste /
Nesse caso, eu pedi para o find encontrar no diretrio em que estou (.) todos os arquivos
(-type f) e para cada um deles executar (-exec) o comando rm. As chaves {} so substitudas
por cada arquivo encontrado pelo find. Dessa forma o rm executado uma vez para cada
arquivo, tendo assim apenas aquele arquivo como parmetro, o que evita ultrapassar o limite
de memria imposto. O final \; para fechar o comando do -exec com um ponto e vrgula,
que precisa ser precedido da contra barra (\) para que a bash no o interprete (uma vez que ;
um caractere com sentido especial para a bash) e apenas o passe para o find.
Caso, por exemplo, voc precise remover somente os arquivos html e no os arquivos .php
em um diretrio, basta usar o find novamente:
> ls *. php
1. php 2. php
> ls
( saida resumida :)
23497. html 36998. html 50498. html 6399. html 774. html 9. html
23498. html 36999. html 50499. html 639. html 77500. html
23499. html 3699. html 5049. html 63. html 77501. html
2349. html 369. html 504. html 64000. html 77502. html
234. html 36. html 50500. html 64001. html 77503. html
> find . - name \*. html - exec rm -f {} \;
> ls
25
1. php 2. php
>
Aqui o asterisco funciona porque est precedido pela contrabarra (\) o que faz com que a
bash no o interprete, apenas o find. E o find no expande o asterisco em todos os arquivos
do diretrio, como a bash. Para o find, o asterisco parte de uma expresso regular, que quer
dizer encontre arquivos cujo nome seja qualquer coisa seguida de um .html .
Eu uso a verso da GNU do find, presente na maioria dos sistemas Linux. Caso o seu find
no entenda o parmetro -exec, use-o em conjunto com comando xargs:
> find . - name \*. html | xargs rm -f
> ls
1. php 2. php
Uma das coisas mais interessantes do Linux poder usar a sada de um programa para a
entrada de outro. Esta dica mostra como substituir determinado texto em todas as ocorrncias
nos arquivos especificados ainda mantendo um backup de segurana dos mesmos usando find,
xargs e nosso amigo Perl. :)
Vamos dissecar o comando:
> find ./ - name '*. php ' | xargs perl -i . bkp -p -e 's / isso / aquilo / ig ; '
O find ./ -name *.php : vai procurar por todos os arquivos .php do diretrio corrente.
O find recursivo por padro, ou seja, ele vai procurar os arquivos .php em todos os subdiretrios do diretrio atual. Se voc no quiser alterar nada nos subdiretrios inclua a diretiva
"-maxdepth 1"para forar o find a trabalhar apenas no primeiro nvel de diretrios, ficando:
> find ./ - maxdepth 1 - name '*. php ' | xargs perl -i . bkp -p -e 's / isso /aquilo / ig ; '
O comando xargs apenas recebe sua entrada da sada do comando find (neste caso, os
nomes dos arquivos) e manda para o Perl, que vai ento:
-i.bkp : criar uma cpia do arquivo com a extenso bkp ou qualquer outra que voc escolher.
-p : executar a leitura dos arquivos em loop, linha a linha.
-e : Executar o comando s/isso/aquilo/ig que significa substituir a palavra "isso"pela
palavra "aquilo", em cada linha dos arquivos.
Os ltimos caracatecres (ig) dizem ao Perl para (i)gnorar maisculas e minsculas e fazer as
alteraes (g)lobalmente, caso sejam encontradas mais de uma ocorrncia da palavra procurada
na mesma linha. Se o "g"for omitido, o Perl somente substituir a primeira ocorrncia da
palavra por cada linha.
O texto de substituio pode ser uma string literal ou uma expresso regular das mais
simples ou complexas, tudo depende de voc, da sua experincia e da complexidade do que
quiser fazer.
26
Um bom exemplo de utilizao se voc tiver um grande website com diversas pginas
que utilizem um include para um ou mais arquivos que por ventura podem ter sua localizao
modificada. Exemplo:
Todos (ou uma grande maioria dos) os arquivos .php possuem um include do arquivo:
/ var / www / htdocs / seudiretorio / scripts . php
De uma hora para outra, seu hosting decide mudar este caminho para: /var/www/localhost/seudireto
Ao invs de editar arquivo por arquivo, execute:
> find ./ - name '*. php ' | xargs perl -i . bkp -p -e
's /(\/ var \/ www \/) \ w +(\/ seudiretorio \/) / $1localhost$2 / ig ; '
O cpio uma ferramenta GNU para criao e extrao de arquivos, movimentao de arquivos
de um local para outro, bem como leitura e escrita de arquivos tar, Tape ARchives.
O cpio tem inmeras opes, tais como, realizao de byte-swapping (alterao de bigendian para little-endian e vice-versa), gravao de uma diversidade de sistemas de arquivos de
diferentes formatos, dentre outras.
A grande vantagem do cpio sobre a ferramenta tar que ele pode utilizar como entrada a
sada de outros comandos, como o find.
Por exemplo, caso se deseje gerar um arquivo tar de todos os arquivos de configurao do
sistema, executa-se o seguite conjunto de comandos:
> find / etc - iname \*. conf | cpio -o -- format = tar > arquivo . tar
possvel acrescentar dados a um arquivo tar j existente. Para tanto, primeiro, gera-se
um arquivo tar com alguns dados:
27
Listando o contedo de um arquivo tar, o que feito por meio da opo -t.
> cpio - it
alternativamente,
> cpio - it -F arquivo . tar
Extraindo o contedo de um arquivo tar. Para este fim, usa-se apenas a opo -i
> cpio -i -F arquivo . tar
Notas: Para realizar backup em fita, basta direcionar a sada o comando cpio para -O
/dev/st0. De maneira anloga, para restaurao do backup pode informar a fita como entrada
do comando -I /dev/st0
A opo -H, format, oferece suporte a uma srie de formatos padro POSIX (Portable
Operating System Interface UniX).
O formato de sada padro bin. O padro para a entrada a autodeteco do formato.
Os formatos vlidos so:
Formato
bin
odc
newc
crc
tar
ustar
hpbin
hpodc
Descrio
binrio.
antigo formato portvel (POSIX.1).
novo formato portvel (SVR4).
novo formato portvel (SVR4) com checksum adicionado.
Tar, Tape ARchives
POSIX.1 tar (tambm reconhece arquivos GNU tar).
binrio HP-UX (j obsoleto).
formato portvel do HP-UX.
Para copiar uma estrutura de pastas sem copiar os arquivos, os seguintes conhecimentos sero
combinados:
Conceito de subshell (executa comandos sem sair do diretrio corrente)
28
Comando find com a opo -type d -print0 lista diretrios e marca como delimitador o
caractere zero.
Comando xargs com a opo 0
mkdir com a opo -p
Tomemos por exemplo a estrutura de uma pasta /docs:
( cd /docs ; find -type d -print0 ) | xargs -0 mkdir -p||+ -> diretrio base
O trecho entre parnteses executado num subshell. A inteno gerar a lista das pastas
partir do diretrio indicado, o -print0 do find ajuda a evitar que pastas com nomes compostos
gerem duas ou mais pastas. Note que o xargs tem tambm uma opo zero 0 para pegar este
delimitador. Outra funo do xargs evitar estouro de pilha. O xargs s entrega ao mkdir
blocos de um tamanho aceitvel sendo muito mais rpido do que a opo "-exec"do find.
Referncias
[1] http://unix.stackexchange.com/questions/34248/how-can-i-find-broken-symlinks.
Acessada em 21/12/2013.
[2] Um boa introduo ao comando find. http://gerencievocemesmo.com.br/site/?p=56.
Acessada em 21/12/2013.
[3] http://www.linuxdescomplicado.com.br/2013/07/comandos-linux-encontre-tudo-que.
html
[4] Foram vistas diversas dicas do comando find no stio: http://www.dicas-l.com.br/.
Acessada em 21/12/2013.
[5] http://www.dicas-l.com.br/cantinhodoshell/cantinhodoshell_20080720.php#
.UrX_qPgdx38. Acessada em 21/12/2013.
[6] http://aurelio.net. Acessada em 21/12/2013.
[7] http://www.cyberciti.biz/faq/howto-find-delete-empty-directories-files-in-unix-linux
Acessada em 21/12/2013.
[8] Verificar
esta
pgina.
http://www.thegeekstuff.com/2009/03/
15-practical-linux-find-command-examples/. Acessada em 25/12/2013
[9] http://how-to.wikia.com/wiki/How_to_find_broken_symbolic_links. Acessada em
26/12/2013.
29