Como encontrar arquivos por tipo de arquivo?

8

Eu sei que posso encontrar arquivos usando find : find . -type f -name 'sunrise' . Exemplo de resultado:

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

Eu também sei que posso determinar o tipo de arquivo de um arquivo: file sunrise . Exemplo de resultado:

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
    
por Flux 24.11.2018 / 15:43

3 respostas

13

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

O utilitário find não pode distinguir, por si só, entre um "script de shell", "arquivo de imagem JPEG" ou qualquer outro tipo de arquivo regular . Esses tipos de dados podem, no entanto, ser distinguidos pelo utilitário file , que examina assinaturas específicas dentro dos próprios arquivos para determinar seu tipo.

Uma forma comum de rotular os diferentes tipos de arquivos de dados é pelo tipo MIME , e file é capaz para determinar o tipo MIME de um arquivo.

Usando file com find para detectar o tipo MIME de arquivos regulares e use isso apenas para localizar 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 do -exec se você quiser apenas detectar 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 shell script em linha curto. 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 cadeia, ela sairá com um status de saída diferente de zero, o que fará com que find continue imediatamente com o próximo arquivo. Se o arquivo foi encontrado para ser um script de shell, o comando find continuará a saída do nome do caminho do arquivo (o -print no final, que também pode ser substituído por alguma outra ação).

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

text/x-shellscript; charset=us-ascii

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

application/x-shellscript

O bit comum é o /x-shellscript de substring.

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

Você desejaria executar alguma ação personalizada em cada script de shell encontrado, você poderia fazer isso com outro -exec no lugar dos comandos -print nos find 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 {} +

Relacionados:

por 24.11.2018 / 16:17
0

Usando perl ' File::LibMagic module:

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' -- .
    
por 24.11.2018 / 23:08
0

Você pode executar find em cada arquivo encontrado e, em seguida, grep para o resultado em que 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 que o padrão de pesquisa seja o mais próximo possível da sua expectativa de manter baixo o número de correspondências falso-positivas.

Tenha em atenção que os ficheiros com novas linhas nos seus nomes de ficheiro podem causar problemas com esta abordagem.

    
por 29.11.2018 / 15:01