Como excluir uma lista de caminhos de diretório completos no comando find no Solaris

3

(duplicado do Stack Overflow: link )

Eu tenho uma necessidade muito específica de encontrar arquivos e diretórios não proprietários no Solaris usando um script, e preciso excluir caminhos completos de diretórios do find, pois eles contêm potencialmente milhares de arquivos sem dono (e é normal porque são arquivos hospedado em outros servidores). Eu nem quero encontrar para pesquisar nesses diretórios, uma vez que irá travar o servidor (cpu spiking para 99% por um longo tempo), portanto, piping os resultados da pesquisa em egrep para filtrar os diretórios não é uma opção.

Eu sei que posso fazer isso para excluir um dos diretórios mais pelo nome:

find / -mount -local \( -type d -a \( -name dir1 -o -name dir2 -o dir3 \) \) -prune -o \( -nouser -o -nogroup \) -print

No entanto, isso corresponderá a dir1 e dir2 em qualquer lugar na estrutura de diretórios de quaisquer diretórios, o que é não o que eu quero.

Eu quero ser capaz de impedir que o mesmo seja encontrado nos seguintes diretórios (como um exemplo):

/opt/dir1
/opt/dir2
/var/dir3/dir4

E eu ainda quero encontrar arquivos e diretórios sem dono nos seguintes diretórios:

/opt/somedir/dir1
/var/dir2
/home/user1/dir1

Eu tentei usar o regex nos argumentos -name, mas desde encontrar apenas as correspondências 'name' contra o nome de base do que encontrar, não posso especificar um caminho. Infelizmente, a descoberta do Solaris não suporta opções de localização do GNU como -wholename ou -path, então estou meio que ferrada.

Meu objetivo seria ter um script com a seguinte sintaxe:

script.sh "/path/to/dir1,/path/to/dir2,/path/to/dir3"

Como eu poderia fazer isso usando o find e o script padrão sh (/ bin / sh) no Solaris (5.8 ou superior)?

    
por Yanick Girouard 22.10.2011 / 07:55

2 respostas

2

Você não pode corresponder arquivos por caminho completo com Solaris find , mas você pode corresponder arquivos por inode. Portanto, use ls -i para gerar uma lista de inodes a serem removidos e, em seguida, chame find . Isso pressupõe que não haja tantos diretórios que você queira remover que você ultrapassaria o limite de comprimento da linha de comando.

inode_matches=$(ls -bdi /opt/dir1 /opt/dir2 /var/dir3/dir4 |
                sed -e 's/ *\([0-9][0-9]*\) .*/-inum  -o/')
find / -xdev \( $inode_matches -nouser -o -nogroup \) -prune -o -print

Uma abordagem alternativa seria usar um script Perl ou Python e rolar o seu próprio diretório transversal. O Perl é fornecido com um script find2perl que pode começar com o módulo File::Find . Em Python, veja a função walk no módulo os.path .

    
por 22.10.2011 / 18:50
2

Como as implementações do find não suportam -path test, você pode simular usando -exec test "{}" = "/path/to/exclude" \; -prune (o {} deve ser expandido para o nome do caminho completo).

Isso, infelizmente, levará mais tempo do que o "puro", já que o programa test será executado em cada execução. Portanto, certifique-se de otimizar os testes o máximo que puder - por exemplo, verificar qual dessas duas execuções é mais rápida:

 -exec test "{}" = "/dev" \; -o -exec test "{}" = "/proc" \; -o -exec test "{}" = "/tmp/test" \;

ou

 -exec test "{}" = "/dev" -o "{}" = "/proc" -o "{}" = "/tmp/test" \;

Acho que o último deve ser mais rápido no geral, porque o programa test é executado apenas uma vez.

Nota: Você não precisa do -a para o e-logic; isso está implícito por padrão. O mesmo vale para -print no final.

    
por 22.10.2011 / 17:10