Você está na página 1de 29

O Comando find do GNU/Linux

Salviano A. Leo
21/12/2013

Sumrio
1 Introduo

2 O comando find
2.1 Parmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2
2

3 Exemplos do comando find


3.1 Buscar, classificar e copiar arquivos . . . . . . . . . .
3.2 Receitas de uso do comando find . . . . . . . . . . .
3.3 Apagando arquivos com o comando find . . . . . . .
3.4 Encontrar e apagar arquivos vazios . . . . . . . . . .
3.5 Evitando as mensagens de erro geradas pelo comando
3.6 Dicas de utilizao do find . . . . . . . . . . . . . . .
3.6.1 Alterando arquivos com o find . . . . . . . . .
3.6.2 Fazendo muita coisa com arquivos alterados .
3.7 O comando find - links rfos . . . . . . . . . . . . .
3.7.1 Como localizar e salvar links simblicos . . . .
3.8 Mais do find . . . . . . . . . . . . . . . . . . . . . . .
3.9 chmod, chown, chgrp, find e xargs . . . . . . . . . . .
3.10 Remoo de diretrios e arquivos vazios . . . . . . . .

. . .
. . .
. . .
. . .
find
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

6
10
10
11
11
12
14
15
15
15
16
18
19
20

4 O comando xargs

21

5 bash - Argument list too long

24

6 Substituindo texto em diversos arquivos ao mesmo tempo

26

7 Criao de arquivos TAR utilizando cpio

27

8 Copiando uma estrutura de pastas sem copiar os arquivos

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

datas do ltimo acesso estejam restrita a algum perodo;


tamanhos estejam restritos a algum valor mnimo ou mximo;
sejam symlinks ou links quebrados;
pertencentes a um determinado usurio ou grupo;
etc.
So essas possibilidades que tornam esta tarefa rdua, porm aqui pretendemos mostrar
como usar o comando find do Linux para realizar essas tarefas.
Encontrar um arquivo no Linux pode ser uma tarefa difcil, principalmente para quem
usa apenas o campo de pesquisa do Nautilus. Via interface grfica (GUI) possvel fazer a
busca por determinado arquivo, contudo existe uma certa ineficincia na exatido da consulta.
Para administradores de sistemas Linux, trabalhar com o comando find imprescindvel por ter
melhores resultados na pesquisa. Em contrapartida para usurios iniciantes ou no-tcnicos isso
uma grande complicao. Portanto, nesse artigo, contm um guia de como usar o comando
find no seu dia-a-dia sem muita dificuldade.
> find -- help
> locate -- help

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

O comando find um dos comandos mais completos que existe no Linux.


Embora muitos achem que desagradvel fazer buscas atravs do terminal, eles desconhecem
o poder de um verdadeiro sistema de busca, principalmente porque a maioria est acostumada
com uma interface grfica.
No se pretende explicar todo o comando find, pois suas possibilidades so enormes, mas
o foco ser nas principais possibilidades do comando find.
Sempre que surgir uma dvida, consulte o manual do find (digite no shell: man find).
Sintaxe:
find [ caminho ...] express o [ a o ]

O comando ir find procurar arquivos pelos nomes e ou outras caractersticas adicionais


como ser visto.

2.1

Parmetros

Os parmetros do comando find so:


caminho Caminho do diretrio a partir do qual o find ir procurar pelos arquivos;
2

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

Tipo de arquivo procurado


Arquivo especial acessado a bloco
Arquivo especial acessado a caractere
Diretrio
Named pipe (FIFO)
Arquivo regular
Link simblico
Socket
Porta (Solaris)

-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

Tambm possvel formatar datas e horas obedecendo s tabelas a seguir:


Caractere
%a
%c
%t

Significado
Data do ltimo acesso
Data de criao
Data de alterao

Os trs caracteres anteriores produzem uma data semelhante ao do comando date.


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 %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)

Tabela de formatao de datas:


Caractere
a
A
b
B
c
d
D
h
j
m
U
w
W
x
y
Y

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

Dec 26 17:35 . bash_history


Nov 29 2004 . bash_logout
Nov 1 09:44 . bash_profile
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 \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

Exemplos do comando find

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

Na pasta /home que contm todos os usurios do sistema:


> find / home - name Arquivo - X

Em todo o sistema, ou seja, em toda a mquina:


> find / - name arquivoX

2) Buscando apenas arquivos, dentro do diretrio atual, que no tenham a extenso .txt:
> find . \!

name

*. txt

Sero exibidos apenas os nomes de arquivos que no contenham a extenso .txt.


3) Buscando pelos arquivo cujo o nome contenham Arq
no incio do nome
> find . - name " Arq * "

no fim do nome
> find . - name " * Arq "

em qualquer parte do nome


> find / - name " * Arq * "

4) Buscando apenas o arquivo Arquivo-X ou apenas a pasta Pasta-X:


Apenas as pastas de nome Pasta-X:
> find / home - type d Pasta - X

Apenas os arquivos de nome :


> find / home - type f Arquivo - X

Apenas links simblicos:


> find / home - type l arquivoX

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

Arquivos e pastas com a permisso dada por: chmod 777


> find / home - 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

Com menos de 6 Mb:


> find / home - type f - size -6 M

Com mais de 450 kb e menos de 10 Mb:


> find / home - type f - size +450 k - size -10 M

Performance: A busca anterior pode ser otimizada com o seguinte comando:


> find / home - type f - size +450 k && -10 M

Consulte o manual para obter mais possibilidades e otimizaes;


7) Buscando arquivos dos usurios do sistema que se encontram no /home verificando as datas
de modificao dos arquivos:
Modificado h N dias, nesse caso note que o N multiplicado por 24 horas automaticamente, assim basta:
> find / home - type f - atime N

Se em N houver uma parte fracionria, ela ser ignorada;


Modificado h at 15 ou no perodo de at N minutos:
> find / home - type f - ctime 15
> find / home - type f - ctime N

Modificado h mais de 7 dias, mas no mais que 15 dias:


> find / home - type f - atime -15 - atime +7

Modificado h pelo menos 20 minutos, mas no mais que 1 hora:


> find / home - type f - ctime +20 - ctime -60

Performance: A busca anterior pode ser otimizada com o seguinte comando:


> find / home - type f - ctime +20 && -60

8) Buscando pelos arquivos de determinados usurios:


> find / home - type f - user root - name Arquivo - X

9) Executando comandos com os arquivos localizados:


Sintaxe:
> find / home - type f - perm 777 - user root - exec chmod 644 {} \;

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

A o n o especificada print default


estes quatro primeiros arquivos foram
encontrados no diret rio corrente .
Estes quatro foram encontrados no
diret rio tstsh , sob o diret rio corrente

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 {} \;

Repare que no exemplo acima usei trs critrios de pesquisa, a saber:


-type f Todos os arquivos regulares (normais)
-size +1000000c Tamanho maior do que 1000000 de caracteres (+1000000c)
-atime +60 ltimo acesso h mais de 60 (+60) dias.
Repare ainda que entre estes trs critrios 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 .sh ou .txt, faria:
> find / - name \*. sh o name \*. txt print

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

Buscar, classificar e copiar arquivos

Aps ter recuperado arquivos de um HD corrompido, usando o testdisk, precisei reorganizar


os arquivos.
O primeiro passo foi classificar por tipo de extenso. Em seguida copi-los para pastas de
acordo com sua extenso. O comando utilizado foi o find, com o parmetro -exec:
> find / home / aderson / discoRecuperado / - type f \( - name " *. doc " -o - name " *.docx " \) \
- print - exec cp -v {} / media / pendrive / documentosWord \;

No exemplo acima, primeiro so localizados todos os arquivos do diretrio discoRecuperado


com as extenses .doc e .docx. Em seguida o parmetro -exec faz com que sejam copiados
todos os arquivos encontrados para a pasta documentosWord.
Feito. Em poucos segundos varri centenas de pastas em busca de arquivos com extenso
.doc e docx. Agora todos eles esto na pasta documentosWord. :)

3.2

Receitas de uso do comando find

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

O mais recomendvel gerar um backup destes arquivos, para em seguida apag-los:


> find . - cpio / dev / rmt0 - nouser

Para restaurar estes arquivos


> cpio - idmv < / dev / rmt0

O comando cpio, a exemplo do comando find, extremamente poderoso e flexvel. Para


mais informaes sobre seu uso e sintaxe, consulte as man pages (ou as prximas dicas :)

3.3

Apagando arquivos com o comando find

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

No meu caso que precisava limpar arquivos de 2008 utilizei:


> find / backups - name " *2009 -*. gz " - delete

Com isto todos os arquivos dos subdiretrios abaixo de /backups que continham 2009 em
seu nome foram deletados.

3.4

Encontrar e apagar arquivos vazios

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

Em ambos os casos as opes usadas foram:


-empty: encontre somente um arquivo/diretrio vazio e certifique-se de que ele um
arquivo/diretrio regular.
-type d: filtre somente os diretrios.
-type f: filtre somente os arquivos.
-delete: Apague os arquivos/diretrios. Est opo sempre deve estar no fim do comando find. Porm quando a linha com o comando find for avaliada com uma expresso, ento ao colocar a opo -delete no incio, o comando find tentar apagar tudo
antes de aplicar a expresso ao arquivos encontrados.

H um segundo mtodo que usando as combinaes do comando xargs e rm/rmdir.


Nesse caso a sintaxe mais segura e rpida do comando para apagar todos os diretrios vazios

> find / home / salviano / tmp - type d - empty - print0 | xargs -0 -I {} / bin /rmdir " {} "

ou podemos usar tambm a seguinte combinao:


> find / home / salviano / tmp - type d - empty - print0 - exec rmdir -v " {} " \;

a qual pode ser um pouco mais lenta devido a opo -exec.


A sintaxe mais segura e rpida do comando para apagar todos os arquivos vazios :
> find / home / salviano / tmp - type f - empty - print0 | xargs -0 -I {} / bin / rm "{} "

ou podemos usar tambm a seguinte combinao:


> find / home / salviano / tmp - type f - empty - print0 - exec rm -v " {} " \;

a qual pode ser um pouco mais lenta devido a opo -exec.

3.5

Evitando as mensagens de erro geradas pelo comando find

Ao emitir o comando find, se no temos os privilgios do superusurio (root), e dependendo


de onde estamos pesquisando, podemos receber uma enxurrada de mensagens de erro, que
atrapalham e muito na visualizao dos resultados:
> find / - name password *
find : '/ lost + found ': Permiss o negada
find : '/ etc / ppp / peers ': Permiss o negada

12

find : '/ etc / cups / ssl ': Permiss o negada


find : '/ etc / chatscripts ': Permiss o negada
find : '/ etc / ssl / private ': Permiss o negada
./ var / lib / pam / password
find : '/ var / lib / mysql ': Permiss o negada

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

No arquivo saida.txt temos o contedo:


/ 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
... linhas omitidas

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

Dicas de utilizao do find

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 comando para procurar por strings (sequncias) especificas e imprimir as strings e os


nomes dos arquivos nas quais elas foram encontradas iro se parecer com:
14

> find . - type f - exec grep " antes " {} \; - print

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

Alterando arquivos com o find

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

Fazendo muita coisa com arquivos alterados

Para se executar um nmero de comandos em cada arquivo que se encontra, h um meio de


faz-lo tambm - e isso no requer a utilizao da opo -exec. Ao contrario, redirecione
(com pipe) a sada do seu comando find normal para um repetidor while como este e pode-se
executar quantos comandos desejar entre os marcadores do e done:
find . - type f | while read i
do
file $i
ls -i $i
wc -l $i
done

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

O comando find - links rfos

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

Isso d conta do recado!


Repare q o 2>/dev/stdout pode ser substituido por 2>&1, mas eu acho o primeiro mais
legivel!
Isso se faz necessario pois o find, ao seguir um link quebrado escreve a mensagem da saida
padro de erro (stderr), por isso temos que redirecionar, para que o cut consiga pegar e passar
pra frente.
Um outro modo de encontrar links rfos
> ( find . - type l | xargs file ) | grep ' broken symbolic link '

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

For information on that, see: http://ynform.org/w/Pub/FindCommandDetectUnixCyclicSymbolicLink


3.7.1

Como localizar e salvar links simblicos

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

"man find"tem todos os outros.


ento para saber quais so os links simblicos de um diretrio e para onde eles apontam,
basta um:
> find / etc - type l - printf " % p -> % l \ n "
/ etc / sysconfig / network - scripts / ifdown -> ../../../ sbin / ifdown
/ etc / sysconfig / network - scripts / ifup -> ../../../ sbin / ifup
/ etc / vers o - conectiva -> conectiva - release
/ etc / rc . d / init . d / smb -> / usr / sbin / samba
/ etc / rc . d / init . d / linuxconf - setup ->
/ usr / lib / linuxconf / conectiva / scripts / S99linuxconf
/ etc / rc . d / rc0 . d / S00killall -> ../ init . d / killall
/ etc / rc . d / rc0 . d / S01halt -> ../ init . d / halt
/ etc / rc . d / rc0 . d / K80random -> ../ init . d / random
/ etc / rc . d / rc0 . d / K75netfs -> ../ init . d / netfs
/ etc / rc . d / rc0 . d / K90network -> ../ init . d / network
...[ e continua ]

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

find " $ {1: -.} " - type l \


- printf " echo % l ; cd % h ; ln -s % l % f ; cd \ $OLDPWD \ n "

exemplo de uso:
> cd / etc ; ln - save > / tmp / reconstroi - links . sh
> cd / etc - novo ; sh / tmp / reconstroi - links . sh

3.8

Mais do find

Como montar um arquivo cpio ignorando alguns arquivos ou diretrios?


A soluo vem com o find. Ao contrrio do que eu pensava, o parmetro name, serve bem
para isto.
Siga o exemplo:
>
>
>
>
a
>
>

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

# v para a mesma area traquila


# veja se seus arquivos est o l

> mkdir -p pasta /{ e , f } # crie um diretorio novo com 2 novos subdiretorios


> find
# veja o c o n t e d o
.
./ a
./ d
./ c
./ b
./ pasta
./ pasta / f
./ pasta / e

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

chmod, chown, chgrp, find e xargs

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

O argumento sleao:sleao identifica o nome do usurio e o grupo ao qual pertence. Fornecer


os dois argumentos opcional, podemos especificar apenas o nome do usurio, como abaixo:
> chown -R sleao sleao

Caso queiramos trocar apenas a propriedade do grupo, o comando outro, chgrp:


> chgrp -R sleao sleao

At aqui tudo bem. Entretanto, frequentemente usamos os comandos chgrp e chown em


conjunto com o comando xargs e find:
> find . - type d | xargs chown -R 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 :

. - type d | xargs chown -R sleao


imposs vel acessar `./ Salviano ': Arquivo ou diret rio n o encontrado
imposs vel acessar `de ': Arquivo ou diret rio n o encontrado
imposs vel acessar ` Araujo ': Arquivo ou diret rio n o encontrado
imposs vel acessar ` Le o ': Arquivo ou diret rio n o encontrado
imposs vel acessar `./ Salviano ': Arquivo ou diret rio n o encontrado
imposs vel acessar `de ': Arquivo ou diret rio n o encontrado
imposs vel acessar ` Araujo ': Arquivo ou diret rio n o encontrado
imposs vel acessar ` Le o / Dia ': Arquivo ou diret rio n o encontrado

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

Remoo de diretrios e arquivos vazios

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

IMPORTANTE: no se esquea que as diretivas do comando find so avaliadas como uma


expresso. Desta forma, se a diretiva -delete for colocada na frente, o comando find ir apagar
tudo que encontrar a partir do ponto inicial de pesquisa. Ao testar um comando find que voc
queira usar mais tarde em conjunto com a diretiva -delete, especifique explicitamente tambm
a diretiva -depth de forma a evitar surpresas desagradveis. Como ao especificar a diretiva
-delete a diretiva -depth implcita, voc no pode usar as diretivas -prune e -delete em
conjunto. Ento, sempre que for executar comandos que removam objetos do sistema, faa um
teste antes para verificar se tudo est certo (fonte: man find)
Outros modos de realizar essa tarefa:
1) Uma verso segura e rpida para remover diretrios vazios:
> find / home / misterx - type d - empty - print0 | xargs -0 -I {} / bin / rmdir" {} "

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 " {} " \;

3) Uma verso segura e rpida para remover arquivos vazios:


> find / home / misterx - type f - empty - print0 | xargs -0 -I {} / bin / rmdir" {} "

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 " {} \;

Este processo tem duas grandes desvantagens sobre o anterior:


1) A primeira bastante visvel: o tempo de execuo deste mtodo muito superior ao
daquele, isso porque o grep ser feito em cada arquivo que lhe for passado pelo find, um-aum, ao passo que com o xargs, ser passada toda, ou na pior das hipteses, a maior parte
possvel, da lista de arquivos gerada pelo find;
2) Dependendo da quantidade de arquivos encontrados que atendem ao find, poderemos
ganhar aquela famosa e fatdica mensagem de erro "Too many arguments"indicando um
estouro da pilha de execuo do grep. Como foi dito no item anterior, se usarmos o xargs
ele passar para o grep a maior quantidade de parmetros possvel, suficiente para no
causar este erro, e caso necessrio executar o grep mais de uma vez.
ATENO! A pessoal do linux que usa o ls colorido que nem porta de tinturaria: nos
exemplos a seguir que envolvem esta instruo, voc devem usar a opo color=none, seno
existem grandes chances dos resultados no 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 diretrio corrente,
pertencentes a um determinado usurio.
A primeira idia que surge , como no caso anterior, usar um comando find, da seguinte
maneira:
> find . - user cara - exec rm -f {} \;

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

> find / bin - type f - follow | \


xargs ls - al | tr -s ' ' | cut - f3 -d ' ' | sort -u

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 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

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

Qual a diferena entre os comandos abaixo?


> find . - user misterx - exec ls {} \;
> find . - user queiroz - print | xargs ls

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.

bash - Argument list too long

Pode ser que voc j tenha tentado dar um comando usando o asterisco * no bash e tenha
obtido este erro:
24

bash : comando : Argument list too long

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 /

Se voc s pode eliminar os arquivos, uma sada usar o comando find.


> find . - type f - exec rm -f {} \;

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

Substituindo texto em diversos arquivos ao mesmo tempo

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 ; '

Se algo der errado na sua expresso regular:


> rm *. php
> rename . php . bkp . php *. php . bkp

Criao de arquivos TAR utilizando cpio

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

ou, pode-se substituir a opo format pela opo -H


> find / etc - iname \*. conf | cpio -o -H tar > arquivo . tar

O mesmo comando, porm, agora sem redirecionamento


> find / etc - iname \*. conf

| cpio -o -- format = tar -F arquivo . tar

ou, de forma alternativa


> find / etc - iname \*. conf | cpio -o -H tar -F arquivo . tar

possvel acrescentar dados a um arquivo tar j existente. Para tanto, primeiro, gera-se
um arquivo tar com alguns dados:

27

> find ../ diretorio1 | cpio -o -- format = tar -F arquivo . tar

Agora, acrescenta-se os dados de um diretorio2 ao arquivo tar recm-criado usando a opo


append, ou -A
> find ../ diretorio2 | cpio -o -- format = tar -- append -F arquivo . tar

Listando o contedo de um arquivo tar, o que feito por meio da opo -t.
> cpio - it

< arquivo . tar

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 mais informaes, utilizar o help da ferramenta:


> cpio -- help

Copiando uma estrutura de pastas sem copiar os arquivos

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