2012-03-21 28 views
8

Potrzebuję zbudować listę wszystkich rozszerzeń plików binarnych znajdujących się w drzewie katalogów.Jak wyświetlić listę wszystkich rozszerzeń plików binarnych w drzewie katalogów?

Głównym pytaniem powinno być rozróżnienie pliku tekstowego od pliku binarnego, a reszta powinna być ciastem.

EDIT: To jest najbliższy, jakie mam lepsze pomysły?

find . -type f|xargs file|grep -v text|sed -r 's:.*\.(.*)\:.*:\1:g' 
+0

Jak o pliku tekstowym UTF-8? Policzyć to jako plik binarny? – PasteBT

+0

Zgodnie z konwencją pliki binarne wykonywalne nie mają rozszerzeń. – jordanm

+0

@jordanm Poza tym gwiazdorem i byciem w śmiałym kolorze. * duck * :) – Kaz

Odpowiedz

11

Oto sztuczka, aby znaleźć pliki binarne:

grep -r -m 1 "^" <Your Root> | grep "^Binary file" 

-m 1 sprawia, że ​​grep nie przeczytać cały plik.

+2

Czystsze i szybsze niż rozwiązanie znalazłem, oto ostatnie polecenie użyłem 'grep -r -m 1"^"apps | grep"^Plik binarny "| sed -r 's:^Binary \ sfile \ s (. *) \ smatches: \ 1: g'' – dukeofgaming

+0

Prosta rura do' awk '{print $ 3}' 'jest prostsza ... –

2

Nie ma różnicy między plikiem binarnym a plikiem tekstowym w systemie Linux. Narzędzie file sprawdza zawartość i domysły. Niestety, nie jest to zbyt pomocne, ponieważ file nie tworzy prostej odpowiedzi "binarnej lub tekstowej"; ma złożony wynik z dużą liczbą przypadków, które musiałbyś przeanalizować.

Jednym ze sposobów jest odczytanie stałego przedrostka pliku, np. 256 bajtów, a następnie zastosowanie heurystyki. Na przykład, czy wszystkie wartości bajtów od 0x0 do 0x7F, unikając kodów kontrolnych, z wyjątkiem zwykłych białych znaków? To sugeruje ASCII? Jeśli istnieją bajty od 0x80 do 0xFF, czy cały bufor (z wyjątkiem jednego kodu na końcu, który może być przycięty) dekoduje jako prawidłowy kod UTF-8? Itd.

Jednym z pomysłów może być podstępne wykorzystywanie narzędzi wykrywających pliki binarne, takie jak GNU diff.

$ diff -r /bin/ls <(echo foo) 
Binary files /bin/ls and /dev/fd/63 differ 

Bez substytucji procesowej, nadal działa:

$ diff -r /bin/ls /dev/null 
Binary files /bin/ls and /dev/null differ 

Teraz tylko grep wyjście to i szukać słowa Binary.

Pytanie brzmi, czy heurystyka diff dla plików binarnych działa dla twoich celów.

+2

Możesz spróbować użyć 'file -i', co spowoduje, że wypisze format pliku jako typ mime. Następnie możesz sprawdzić, czy typ MIME ma przedrostek 'text /'. Myślę, że to może działać całkiem nieźle. –

+0

Dobrze wiedzieć, dzięki! Przeglądałem stronę man w poszukiwaniu bardziej skondensowanej przestrzeni wyjściowej z 'file', ale tego nie zauważyłem. – Kaz

1

Nie ma pewności, jak odróżnić plik "tekstowy" od pliku "binarnego", to zgadnij.

#!/bin/bash 
guess=`echo \`head -c 4096 $1 | strings -a -n 1 | wc -c \` '* 1.05 /' \`head -c 4096 $1 | wc -c \` | bc `; 
if [ $guess -eq 1 ] ; then 
    echo $1 "is text file" 
    exit 0 
else 
    echo $1 "is binary file" 
    exit 1 
fi 
4

Ten perly jedno-liner pracował dla mnie, było również dość szybko:

find . -type f -exec perl -MFile::Basename -e 'print (-T $_ ? "" : (fileparse ($_, qr/\.[^.]*/))[2] . "\n") for @ARGV' {} + | sort | uniq 

i to w jaki sposób można znaleźć wszystkie pliki binarne w bieżącym folderze:

find . -type f -exec perl -e 'print (-B $_ ? "$_\n" : "") for @ARGV' {} + 

-T jest testem dla plików tekstowych, a -B dla binarnego i są one względem siebie przeciwieństwem *.

* perl file tests doc

0

Oto jeden-liner w Pythonie, aby sprawdzić, czy plik jest binarny:

b"\x00" in open("/etc/hosts", "rb").read() 

Znajdź używając go rekurencyjnie w skorupkach, patrz poniższy przykład:

IS_BINARY='import sys; sys.exit(not b"\x00" in open(sys.argv[1], "rb").read())' 
find . -type f -exec bash -c "python -c '$IS_BINARY' {} && echo {}" \; 

Aby znaleźć wszystkie pliki niebinarne, zmień && na ||.

0

Oto proste polecenie do listy wszystkich plików binarnych (które składają NULL character) za pomocą GNU grep:

grep -Palr '\x00' . 

Aby wydrukować rozszerzenie pliku krótszy niż 5 znaków możemy użyć awk a następnie odfiltrować duplikaty za pomocą albo uniq lub sort.

Więc wszystko razem powinno być coś takiego:

grep -Palr '\x00' . | awk -F. '{if (length($NF) < 5) print $NF}' | sort -u 
Powiązane problemy