Como encontrar arquivos por tipo de arquivo?

Sei que posso encontrar arquivos usando find: find . -type f -name "sunrise" . Resultado de exemplo:

./sunrise ./events/sunrise ./astronomy/sunrise ./schedule/sunrise 

Também sei que posso determinar o tipo de arquivo de um arquivo: file sunrise. Resultado de exemplo:

sunrise: PEM RSA private key 

Mas como posso encontrar arquivos por tipo de arquivo?

Por exemplo, my-find . -type f -name "sunrise" -filetype=bash-script:

./astronomy/sunrise ./schedule/sunrise 

Comentários

  • Não há --filetype opção para o comando find ou qualquer outra coisa que indique o tipo de arquivo. A única coisa que você pode fazer é usar --exec file {} \; e, em seguida, canalizá-lo para grep Bourne se estiver procurando por scripts bash ou grep Perl se você estiver procurando por scripts Perl ou algo parecido.

Resposta

“Tipos de arquivo” em um sistema Unix são coisas como arquivos regulares, diretórios, canais nomeados, arquivos especiais de caracteres, links simbólicos etc. Estes são os tipos de arquivos que find podem filtrar com sua -type opção.

O find não pode, por si só, distinguir entre um “script de shell”, “arquivo de imagem JPEG” ou qualquer outro tipo de arquivo regular . No entanto, esses tipos de dados podem ser diferenciados pelo utilitário file, que analisa assinaturas específicas nos próprios arquivos para determinar seu tipo.

Uma maneira comum de rotular os diferentes tipos de arquivos de dados são pelo seu tipo MIME e file é capaz de determinar o tipo MIME de um arquivo.


Usando file com find para detectar o tipo MIME de arquivos regulares, e use isso para encontrar apenas scripts de shell:

find . -type f -exec sh -c " case $( file -bi "$1" ) in */x-shellscript*) exit 0 esac exit 1" sh {} ";" -print 

ou, usando bash,

find . -type f \ -exec bash -c "[[ "$( file -bi "$1" )" == */x-shellscript* ]]" bash {} ";" \ -print 

Adicione -name sunrise antes de -exec se desejar detectar apenas scripts com esse nome.

O comando find acima encontrará todos os arquivos regulares dentro ou abaixo do diretório atual e, para cada um desses arquivos, chame um script de shell curto em linha. Este script executa file -bi no arquivo encontrado e sai com um status de saída zero se a saída desse comando contiver a string /x-shellscript. Se a saída não contiver essa string, ela sai com um status de saída diferente de zero que faz com que find continue imediatamente com o próximo arquivo. Se o arquivo for um script de shell, o comando find continuará a gerar o caminho do arquivo “s (o -print no fim, que também pode ser substituído por alguma outra ação).

O comando file -bi produzirá o tipo MIME do arquivo. Para um script de shell no Linux ( e a maioria dos outros sistemas), seria algo como

text/x-shellscript; charset=us-ascii 

enquanto em sistemas com uma variante um pouco mais antiga do file utilitário, pode ser

application/x-shellscript 

O bit comum é a /x-shellscript substring.

Observe que no macOS, você teria que usar file -bI em vez de file -bi devido a razões (o -i opção faz algo bem diferente). A saída no macOS é semelhante à de um sistema Linux.


Você gostaria de realizar alguma ação personalizada em cada shell script encontrado, você poderia fazer o com outro -exec no lugar do -print nos find comandos acima, mas também seria possível fazer

find . -type f -exec sh -c " for pathname do case $( file -bi "$pathname" ) in */x-shellscript*) ;; *) continue esac # some code here that acts on "$pathname" done" sh {} + 

ou, com bash,

find . -type f -exec bash -c " for pathname do [[ "$( file -bi "$pathname" )" != */x-shellscript* ]] && continue # some code here that acts on "$pathname" done" bash {} + 

Relacionado:

Resposta

Você poderia executar find em cada arquivo encontrado e, em seguida, grep para o resultado no qual você “está interessado.

# When looking for ASCII Text find . -type -exec file {} \; | grep "ASCII" # or for MS Word Documents find . -type f -exec file {} \; | grep "Microsoft Word" 

Sugiro tornar o padrão de pesquisa o mais próximo possível de sua expectativa para manter o número de o falso positivo corresponde a um valor baixo.

Cuidado, pois os arquivos com novas linhas em seus nomes podem causar problemas com essa abordagem.

Resposta

Usando o módulo perl” s File::LibMagic:

perl -MFile::LibMagic=:easy -MFile::Find -le " find sub { print $File::Find::name if $_ eq "sunrise" and -f and MagicFile$_ eq "PEM RSA private key" }, @ARGV" -- . 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *