Як праверыць, ці з'яўляецца файл двайковы файл і чытаць усе файлы, якія не з'яўляюцца?

Як я магу ведаць, калі файл з'яўляецца двайковым файлам?

Напрыклад, складзены файл Сі.

Я хачу, каб прачытаць усе файлы з якога-небудзь каталога, але я хачу ігнараваць двайковыя файлы.

35
дададзена аўтар kenorb, крыніца
дададзена аўтар kenorb, крыніца
У канчатковым рахунку <�я> усе <�я /> файлы з'яўляюцца двайковымі. Тэкставыя файлы проста так, каб утрымліваць двайковыя прадстаўлення чалавечага разумення знакавых дадзеных. Ні адзін метад для вылучэння тэксту з нежывога тэксту не можа быць 100% надзейным.
дададзена аўтар Keith Thompson, крыніца
У канчатковым рахунку <�я> усе <�я /> файлы з'яўляюцца двайковымі. Тэкставыя файлы проста так, каб утрымліваць двайковыя прадстаўлення чалавечага разумення знакавых дадзеных. Ні адзін метад для вылучэння тэксту з нежывога тэксту не можа быць 100% надзейным.
дададзена аўтар Keith Thompson, крыніца

13 адказы

Выкарыстоўвайце ўтыліту Файл , выкарыстанне ўзору:

 $ file /bin/bash
 /bin/bash: Mach-O universal binary with 2 architectures
 /bin/bash (for architecture x86_64):   Mach-O 64-bit executable x86_64
 /bin/bash (for architecture i386): Mach-O executable i386

 $ file /etc/passwd
 /etc/passwd: ASCII English text

 $ file code.c
 code.c: ASCII c program text

Файл старонкавае кіраўніцтва

40
дададзена
@ 4dan - магчыма - мім ? :)
дададзена аўтар Bach, крыніца
Адказ павінен змяшчаць - мім сцяг, як гэта інакш не рэалістычна, каб адпавядаць выходны файл для ўсіх магчымых бінарных фарматаў (напрыклад, рэгулярны выраз занадта доўгім і далікатным).
дададзена аўтар yugr, крыніца
1. Ці існуе, што праца на не-x86 архітэктуры? 2. Вы лічыце PDF-файл бінарны файл?
дададзена аўтар Victor Eijkhout, крыніца
@ 4dan працуе для мяне: Файл -BL --mime "$ шлях" | Grep -q '^ тэкст . Опцыя -b выдаляе імя файла з высновы, і -L разыменовывает сімлінкі.
дададзена аўтар wjandrea, крыніца
Разгледзіце магчымасць выкарыстання «файла --mine». Для двайковых файлаў ён паведамляе «... кадовак = двайковыя», так што можна проста адлучыць інфармацыю назваў паведамленняў "бінарнай $".
дададзена аўтар 4dan, крыніца

Выкарыстоўвайце ўтыліту Файл , выкарыстанне ўзору:

 $ file /bin/bash
 /bin/bash: Mach-O universal binary with 2 architectures
 /bin/bash (for architecture x86_64):   Mach-O 64-bit executable x86_64
 /bin/bash (for architecture i386): Mach-O executable i386

 $ file /etc/passwd
 /etc/passwd: ASCII English text

 $ file code.c
 code.c: ASCII c program text

Файл старонкавае кіраўніцтва

40
дададзена
@ 4dan - магчыма - мім ? :)
дададзена аўтар Bach, крыніца
Адказ павінен змяшчаць - мім сцяг, як гэта інакш не рэалістычна, каб адпавядаць выходны файл для ўсіх магчымых бінарных фарматаў (напрыклад, рэгулярны выраз занадта доўгім і далікатным).
дададзена аўтар yugr, крыніца
1. Ці існуе, што праца на не-x86 архітэктуры? 2. Вы лічыце PDF-файл бінарны файл?
дададзена аўтар Victor Eijkhout, крыніца
@ 4dan працуе для мяне: Файл -BL --mime "$ шлях" | Grep -q '^ тэкст . Опцыя -b выдаляе імя файла з высновы, і -L разыменовывает сімлінкі.
дададзена аўтар wjandrea, крыніца
Разгледзіце магчымасць выкарыстання «файла --mine». Для двайковых файлаў ён паведамляе «... кадовак = двайковыя», так што можна проста адлучыць інфармацыю назваў паведамленняў "бінарнай $".
дададзена аўтар 4dan, крыніца

Adapted from excluding binary file

find . -exec file {} \; | grep text | cut -d: -f1
9
дададзена
Калі (як я), вы знойдзеце \; асабліва пачварны, звярніце ўвагу, што ў шматлікіх выпадках + (POSIX-сумяшчальны) будзе рабіць, а таксама: знайсці ... -exec Foo {} + падобны знайсці ... | xargs Foo .
дададзена аўтар Alois Mahdal, крыніца
Дзякуй, выкарыстоўваецца і адрэгулявана яго, каб знайсці ўсе бінарныя файлы ў тэчцы: знайсці. -тыпу е -exec файл {} \; | Grep -v тэкст | выразаць -d: -f1
дададзена аўтар Gerrit, крыніца
@Jens Дзякуй за напамін. Проста праверце файл , на старонцы Даведніка ён павінен быць тэкст .
дададзена аўтар gongzhitaao, крыніца
Гэта павінна быць Grep тэкст ; гістарычна файл не заўсёды кажуць ASCII, а хутчэй «тэкст сцэнара абалонкі», напрыклад.
дададзена аўтар Jens, крыніца
Я проста зразумеў, што вынаходзіў кола яшчэ раз: для файла ў знайсці. -тыпу е -exec файл {} \; | Grep тэкст | Perl -Nle 'Раскол /: /; друк $ _ [0] ; рабіць Grep -i --color 'string_to_search' $ файла; зроблена;
дададзена аўтар Yordan Georgiev, крыніца
і што, калі імя файла ўтрымлівае слова «тэкст»? Я выкарыстоўваю Grep "* :. * Тэкст" Цяпер
дададзена аўтар Algoman, крыніца
@Algoman Я выкарыстоўваю файл -b , які не выводзіць імя файла. (Можа быць ДНУ толькі функцыя).
дададзена аўтар wjandrea, крыніца

Я выкарыстоўваю

! grep -qI . $path

Адзіны недахоп я бачу ў тым, што ён будзе лічыць пусты файл бінарны, але зноў жа, хто вырашае, калі гэта не так?

8
дададзена
Пусты корпус файл можна кіраваць шляхам дадання || ! Test -s $ шлях .
дададзена аўтар yugr, крыніца
perl -E 'exit((-B $ARGV[0])?0:1);' file-to-test

Можа быць выкарыстана для праверкі, калі «файл да выпрабавання» з'яўляецца двайковым. Вышэйназваная каманда выйдзе досціп код 0 бінарных файлаў, у адваротным выпадку код завяршэння будзе 1.

Зваротны праверка тэкставага файла можа выглядаць наступным чынам каманды:

perl -E 'exit((-T $ARGV[0])?0:1);' file-to-test

Аналагічна, каманда вышэй будзе выходзіць са статусам 0, калі «файл-к-тэст» з'яўляецца тэкст (не бінарны).

Больш падрабязна пра -B і -T правярае з дапамогай каманды perldoc -f -X .

4
дададзена
дададзена аўтар Onlyjob, крыніца

BSD Grep

Here is a simple solution to check for a single file using BSD Grep (on macOS/Unix):

grep -q "\x00" file && echo Binary || echo Text

які ў асноўным правярае, калі файл складаецца NUL характар.

Выкарыстоўваючы гэты метад, каб прачытаць усё недвоичных файлы рэкурсіўна, выкарыстоўваючы знайсці утыліты вы можаце зрабіць:

find . -type f -exec sh -c 'grep -q "\x00" {} || cat {}' ";"

Ці яшчэ прасцей, выкарыстоўваючы толькі Grep :

grep -rv "\x00" .

Для толькі бягучай тэчкі, выкарыстоўвайце:

grep -v "\x00" *

На жаль, прыведзеныя вышэй прыклады не будуць працаваць на GNU Grep , аднак ёсць абыходны шлях.

GNU Grep

Паколькі GNU Grep ігнаруе NULL сімвалаў, то можна праверкі іншых знакаў не-ASCII як :

$ grep -P "[^\x00-\x7F]" file && echo Binary || echo Text

. Заўвага: Гэта не будзе працаваць на файлы, якія змяшчаюць толькі NULL сімвалы

3
дададзена
@VladimirPanteleev Я дадаў больш універсальны метад , які працуе як для Grep версіі, калі ласка, праверце.
дададзена аўтар kenorb, крыніца
Я выкарыстоўваю BSD Grep на MacOS, гэта, здаецца, працуе на ім, а не на GNU адзін.
дададзена аўтар kenorb, крыніца
Якая версія Grep гэта? З GNU Grep 3.1, пошук \ x00 заўсёды церпіць няўдачу.
дададзена аўтар Vladimir Panteleev, крыніца

Выкарыстанне Perl убудаванага -T тэставага файла аператар, пераважна пасля таго, як пераканацца, што гэта звычайны файл, выкарыстоўваючы -f тэставага файла аператар:

$ perl -le 'for (@ARGV) { print if -f && -T }' \
    getwinsz.c a.out /etc/termcap /bin /bin/cat \
    /dev/tty /usr/share/zoneinfo/UTC /etc/motd
getwinsz.c
/etc/termcap
/etc/motd

Вось дадатак гэтага мноства:

$ perl -le 'for (@ARGV) { print unless -f && -T }' \
    getwinsz.c a.out /etc/termcap /bin /bin/cat \
    /dev/tty /usr/share/zoneinfo/UTC /etc/motd
a.out
/bin
/bin/cat
/dev/tty
/usr/share/zoneinfo/UTC
2
дададзена

cat+grep

Мяркуючы, што бінарнік азначае файл, які змяшчае NULL сімвалы, гэтая каманда абалонкі можа дапамагчы:

(cat -v file.bin | grep -q "\^@") && echo Binary || echo Text

альбо:

grep -q "\^@" <(cat -v file.bin) && echo Binary

Гэта абыходны шлях для Grep -q "\ x00" , які працуе для BSD Grep, але не для GNU версіі.

У асноўным -v для кошка пераўтворыць ўсе непечатаемые сімвалы такім чынам, яны бачныя ў выглядзе кіраўнікоў сімвалаў, напрыклад:

$ printf "\x00\x00" | hexdump -C
00000000  00 00                                             |..|
$ printf "\x00\x00" | cat -v
^@^@
$ printf "\x00\x00" | cat -v | hexdump -C
00000000  5e 40 5e 40                                       |^@^@|

дзе ^ @ сімвалы ўяўляюць NULL характар. Таму, як толькі гэтыя кіраўнікі сімвалы выяўленыя, мы мяркуем, што файл з'яўляецца двайковым.


Недахоп вышэй спосаб з'яўляецца тое, што ён можа генераваць ілжывыя спрацоўвання, калі сімвалы не ўяўляюць кіраўнікі знакамі. Напрыклад:

$ printf "\x00\x00^@^@" | cat -v | hexdump -C
00000000  5e 40 5e 40 5e 40 5e 40                           |^@^@^@^@|

Глядзіце таксама: Як адлучыць інфармацыю ўсіх не-ASCII сімвалаў .

1
дададзена
Дададзена нататка, таксама праверце: Як Grep для ўсіх не-ASCII ў UNIX .
дададзена аўтар kenorb, крыніца
Гэта дае ілжывы вынік «Binary» з тэкставым файлам, які змяшчае тры ASCII сімвалаў \ ^ @ .
дададзена аўтар Vladimir Panteleev, крыніца

Сыходзячы Баха рэкамендацыі , я думаю, - мім-кадаваньне гэта лепшы сцяг атрымаць нешта надзейнае з noreferrer "> файла

1
дададзена
@yugr, што цікава - гэта амаль падобна на памылку ў файл , паколькі .docx друкуе файл двайковы для - мім кадаваньне .
дададзена аўтар dimo414, крыніца
Пададзены bugs.astron.com/view.php?id=18
дададзена аўтар dimo414, крыніца
І гэта ўжо было выпраўлена!
дададзена аўтар dimo414, крыніца
Не будзе працаваць для дакументаў Word ( прыкладання/mswordbinary ).
дададзена аўтар yugr, крыніца
Звычайны - мім робіць працуе, хоць ( прыкладання/MSWord, кадоўка = двайковы ).
дададзена аўтар yugr, крыніца

Паспрабуйце наступныя параметры каманднага радка:

file "$FILE" | grep -vq 'ASCII' && echo "$FILE is binary"
1
дададзена
Добры, але абдураныя urt8 файл ASCII. Я выкарыстаў: файл "$ FILE" | Grep -vq 'тэкст'
дададзена аўтар Neil McGill, крыніца

<�Код> Grep

Мяркуючы, што двайковы файл, які змяшчае сродак непечатаемые сімвалы (за выключэннем пустых знакаў, такіх як прабелы, знакі табуляцыі або сімвалы новай радкі), гэта можа працаваць (як BSD і GNU):

$ grep '[^[:print:][:blank:]]' file && echo Binary || echo Text

Note: GNU <�Код> Grep will report file containing only NULL characters as text, but it would work correctly on BSD version.

Дадатковыя прыклады см. Як адлучыць інфармацыю ўсіх не-ASCII сімвалаў

0
дададзена

Вы можаце зрабіць гэта таксама за кошт выкарыстання дифф каманды. Праверце гэты адказ:

HTTPS: //unix.stackexchange.com/questions/275516/is-there-a-convenient-way-to-classify-files-as-binary-or-text#answer-402870

0
дададзена

It's kind of brute force to exclude binary files with tr -d "[[:print:]\n\t]" < file | wc -c, but it is no heuristic guesswork either.

find . -type f -maxdepth 1 -exec /bin/sh -c '
   for file in "[email protected]"; do
      if [ $(LC_ALL=C LANG=C tr -d "[[:print:]\n\t]" < "$file" | wc -c) -gt 0 ]; then
         echo "${file} is no ASCII text file (UNIX)"
      else
         echo "${file} is ASCII text file (UNIX)"
      fi
   done
' _ '{}' +

Наступны пераборам падыход з выкарыстаннем Grep -a -m 1 $ '[^ [: друк:] \ т]' файл здаецца, зусім трохі хутчэй, хоць.

find . -type f -maxdepth 1 -exec /bin/sh -c '
   tab="$(printf "\t")"
   for file in "[email protected]"; do
      if LC_ALL=C LANG=C grep -a -m 1 "[^[:print:]${tab}]" "$file" 1>/dev/null 2>&1; then
         echo "${file} is no ASCII text file (UNIX)"
      else
         echo "${file} is ASCII text file (UNIX)"
      fi
   done
' _ '{}' + 
0
дададзена