Come trovare i file per tipo di file?


9

So che posso trovare i file utilizzando find: find . -type f -name 'sunrise'. Risultato di esempio:

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

So anche che posso determinare il tipo di file di un file: file sunrise. Risultato di esempio:

sunrise: PEM RSA private key

Ma come posso trovare i file per tipo di file?

Ad esempio my-find . -type f -name 'sunrise' -filetype=bash-script:

./astronomy/sunrise
./schedule/sunrise

1
Non esiste alcuna --filetypeopzione per il comando find o qualsiasi altra cosa che ti dirà il tipo di file. L'unica cosa che puoi fare è usare --exec file {} \;e poi reindirizzarlo grep Bournese stavi cercando script bash o grep Perlse stavi cercando script Perl o qualcosa del genere.
Nasir Riley,

Risposte:


13

I "tipi di file" su un sistema Unix sono cose come file regolari, directory, pipe nominate, file speciali di caratteri, collegamenti simbolici ecc. Questi sono i tipi di file che findpossono filtrare con la sua -typeopzione.

L' findutilità non può di per sé distinguere tra "script di shell", "file di immagine JPEG" o qualsiasi altro tipo di file normale . Questi tipi di dati possono tuttavia essere distinti filedall'utilità, che esamina determinate firme all'interno dei file stessi per determinarne il tipo.

Un modo comune per etichettare i diversi tipi di file di dati è in base al loro tipo MIME ed fileè in grado di determinare il tipo MIME di un file.


Utilizzare filecon findper rilevare il tipo MIME di file regolari e utilizzarlo per trovare solo script di shell:

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

o, usando bash,

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

Aggiungi -name sunriseprima del -execse desideri rilevare solo script con quel nome.

Il findcomando sopra troverà tutti i file regolari dentro o sotto la directory corrente e per ciascuno di questi file chiama uno script shell in linea breve. Questo script viene eseguito file -bisul file trovato ed esce con uno stato di uscita pari a zero se l'output di quel comando contiene la stringa /x-shellscript. Se l'output non contiene quella stringa, esce con uno stato di uscita diverso da zero che fa sì findche continui immediatamente con il file successivo. Se il file risulta essere uno script di shell, il findcomando procederà all'output del percorso del file ( -printalla fine, che potrebbe anche essere sostituito da qualche altra azione).

Il file -bicomando genererà il tipo MIME del file. Per uno script di shell su Linux (e la maggior parte degli altri sistemi), questo sarebbe qualcosa di simile

text/x-shellscript; charset=us-ascii

mentre su sistemi con una variante leggermente più vecchia filedell'utilità, potrebbe essere

application/x-shellscript

Il bit comune è la /x-shellscriptsottostringa.

Nota che su macOS, dovresti utilizzare file -bIinvece file -biper motivi (l' -iopzione fa qualcosa di molto diverso). L'output su macOS è simile a quello di un sistema Linux.


Vorresti eseguire qualche azione personalizzata su ogni script di shell trovato, potresti farlo con un altro -execal posto di -printnei findcomandi sopra, ma sarebbe anche possibile farlo

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 {} +

o, con 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 {} +

Relazionato:


1

Puoi eseguire findsu ogni file trovato e quindi grep per il risultato che ti interessa.

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

Suggerisco di rendere il modello di ricerca il più vicino possibile alle vostre aspettative per mantenere basso il numero delle corrispondenze di falsi positivi.

Fai attenzione che i file con nuove righe nei nomi dei file potrebbero causare problemi con questo approccio.


0

Utilizzando perlil File::LibMagicmodulo:

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' -- .
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.