Maneira rápida de determinar se um arquivo é um banco de dados SQLite

7

Estou procurando uma maneira de determinar os tipos de arquivos em uma pasta com milhares de arquivos. Nomes de arquivos não revelam muito e não têm extensão, mas são tipos diferentes. Especificamente, estou tentando determinar se um arquivo é um banco de dados sqlite.

Ao usar o comando file , ele determina o tipo de 2 a 3 arquivos por segundo. Esta parece ser uma boa maneira de resolver o problema, exceto que é muito lento.

Então eu tentei abrir cada arquivo com o sqlite3 e checar se eu recebo um erro. Dessa forma, posso verificar 4-5 arquivos por segundo. Muito melhor, mas acho que pode haver uma maneira melhor de fazer isso.

    
por dmars 21.09.2012 / 23:32

3 respostas

6

2-3 arquivos por segundo testados com file parecem muito lentos para mim. O file efectua vários testes diferentes para tentar determinar o tipo de ficheiro. Como você está procurando um tipo específico de arquivo (sqlite) e não se importa em identificar todos os outros, é possível experimentar um arquivo sqlite conhecido para determinar qual teste realmente o identifica. Você pode então excluir os outros usando o sinalizador -e e executar em seu conjunto de arquivos completo. Veja a página do manual :

 -e, --exclude testname
         Exclude the test named in testname from the list of tests made to
         determine the file type. Valid test names are:

         apptype
            EMX application type (only on EMX).
         text
            Various types of text files (this test will try to guess the
            text encoding, irrespective of the setting of the ‘encoding’
            option).
         encoding
            Different text encodings for soft magic tests.
         tokens
            Looks for known tokens inside text files.
         cdf
            Prints details of Compound Document Files.
         compress
            Checks for, and looks inside, compressed files.
         elf
            Prints ELF file details.
         soft
            Consults magic files.
         tar
            Examines tar files.

Edit: Eu mesmo tentei alguns testes. Resumo:

  1. A aplicação do meu conselho com os sinalizadores certos pode acelerar file em cerca de 15%, para testes para determinar o sqlite. O que é algo, mas não a grande melhoria que eu esperava.
  2. Seus testes de arquivo são muito lentos. Eu fiz 500 em uma máquina padrão no tempo que você fez 2-3. Você está com hardware lento ou verificando arquivos enormes, executando uma versão antiga de file ou ...?
  3. Você deve manter o teste 'soft' para identificar com êxito um arquivo como sqlite.

Para um arquivo DB de sqlite de 16 MB, eu fiz:

#!/bin/bash
for  i in {1..1000}
do
    file sqllite_file.db | tail > out
done

Tempo na linha de comando:

~/tmp$ time ./test_file_times.sh; cat out

real    0m2.424s
user    0m0.040s
sys 0m0.288s
sqllite_file.db: SQLite 3.x database

Ao tentar o teste diferente, exclui, e assumindo que a determinação é feita com base em um único teste, é o teste 'soft' (ou seja, pesquisa de arquivo mágica) que identifica o arquivo. Por conseguinte, modifiquei o comando file para excluir todos os outros testes:

file -e apptype -e ascii -e encoding -e tokens -e cdf -e compress -e elf -e tar sqllite_file.db | tail > out

Executando isso 1.000 vezes:

~/tmp$ time ./test_file_times.sh; cat out

real    0m2.119s
user    0m0.060s
sys         0m0.280s
sqllite_file.db: SQLite 3.x database
    
por 21.09.2012 / 23:50
3

Se você observar a descrição mágica de file para arquivos sqlite, ela procurará SQLite format 3 ou ** This file contains an SQLite no início do arquivo.

Você pode criar um arquivo mágico apenas com essas verificações (e desabilitar os testes incorporados como na solução @ire_and_curses) ou fazer a verificação manualmente:

case $(head -c 31 < "$file") in
  ("** This file contains an SQLite"*) echo sqlite 2;;
  ("SQLite format 3"*) echo sqlite 3;;
esac

Não é muito eficiente, pois executa um head por arquivo. Com um pouco de esforço, você provavelmente poderia fazê-lo em perl, para ler os primeiros 31 bytes de vários arquivos em uma invocação perl.

    
por 22.09.2012 / 00:48
2

Se você olhar para: link , o formato SQLite começa com a string "SQLite format 3 \ 000". Parece-me que você poderia verificar head -c 16 do arquivo para verificar o formato. Eu esperaria que isso fosse mais rápido do que usar ferramentas de propósito geral.

    
por 22.09.2012 / 02:47