Hur hittar jag filer efter filtyp?

Jag vet att jag kan hitta filer med find: find . -type f -name "sunrise" . Exempel på resultat:

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

Jag vet också att jag kan bestämma filtypen för en fil: file sunrise. Exempel på resultat:

sunrise: PEM RSA private key 

Men hur kan jag hitta filer efter filtyp?

Till exempel my-find . -type f -name "sunrise" -filetype=bash-script:

./astronomy/sunrise ./schedule/sunrise 

Kommentarer

  • Det finns ingen --filetype -alternativ för sökkommandot eller något annat som berättar vilken typ av fil. Det enda du kan göra är att använda --exec file {} \; och sedan rör det till grep Bourne om du letade efter bash-skript eller grep Perl om du letade efter Perl-skript eller något i den riktningen.

Svar

”Filtyper” på ett Unix-system är saker som vanliga filer, kataloger, namngivna rör, karaktärspecifika filer, symboliska länkar etc. Det här är typen av filer som find kan filtrera vidare med alternativet -type.

find verktyget kan inte i sig skilja mellan ett ”skalskript”, ”JPEG-bildfil” eller någon annan typ av vanlig fil . Dessa typer av data kan emellertid särskiljas av verktyget file, som tittar på särskilda signaturer i själva filerna för att bestämma deras typ.

Ett vanligt sätt att märka de olika typerna av datafiler är enligt deras MIME-typ , och file kan bestämma MIME-typen för en fil.


Använd file med find för att upptäcka MIME-typen av vanliga filer och använd den för att bara hitta skalskript:

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

eller med bash,

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

Lägg till -name sunrise före -exec om du bara vill upptäcka skript med det namnet.

Kommandot find ovan hittar alla vanliga filer i eller under den aktuella katalogen, och för varje sådan fil anropas ett kort in-line skalskript. Det här skriptet kör file -bi på den hittade filen och avslutas med nollutgångsstatus om utdata från det kommandot innehåller strängen /x-shellscript. Om utdata inte innehåller den strängen, avslutas den med en utgångsstatus som inte är noll vilket gör att find fortsätter omedelbart med nästa fil. Om filen visade sig vara ett skalskript, kommer kommandot find att fortsätta att mata ut filens sökväg (-print vid slut, som också kan ersättas av någon annan åtgärd).

Kommandot file -bi skickar MIME-typen av filen. För ett skalskript på Linux ( och de flesta andra system) skulle detta vara ungefär som

text/x-shellscript; charset=us-ascii 

medan det är på system med en något äldre variant av file -verktyg, det kan vara

application/x-shellscript 

Den gemensamma biten är /x-shellscript -strängen.

Observera att på macOS måste du använda file -bI istället för file -bi på grund av skäl ( -i -alternativet gör något helt annat). Utdata på macOS liknar det för ett Linux-system.


Vill du utföra en anpassad åtgärd på varje hittat skalskript kan du göra det at med en annan -exec i stället för -print i find kommandona ovan, men det skulle det också vara möjligt att göra

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

eller, med 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 {} + 

Relaterat:

Svar

Du kan köra find på varje hittad fil och sedan grep för det resultat du är intresserad av.

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

Jag föreslår att du gör sökmönstret så nära din förväntan att behålla antalet de falska positiva matchningarna är låga.

Observera att filer med nya rader i deras filnamn kan orsaka problem med detta tillvägagångssätt.

Svar

Med perl” s File::LibMagic -modul:

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" -- . 

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *