Grep – Why ‘Binary File Matches’ with Grep -I?

binarygrep

In the following example, grep behaves strangely: it's supplied with -I option, which, according to man page, should make grep ignore binary files (similarly to --binary-files=without-match), but I still get the "Binary file matches" output.

$ cat <<'EOF' | uudecode > test-file
begin 664 /dev/stdout
M>`&5SLU*Q$`0!&#/>8J^"TM/=^8/1%2\>1`\>.^9Z=D-9!))9@7?WBB^@%"G
MHOBHO+8V=2!'-WU3A9PX%*8PBB:VGK@6)Y*HFAB(.2;.;$SQPX=LNG3(>2SH
MDJE!5;R+E9P21J::8U2+?@R>RK&7:[^L&[Q=]UD6>)$D?9<O_82[Y$\&S4_,
MP[G)-)_RVN[!6(S.>F0/M\B(P]$>5[O^%_$8+/(?,CSI+]%DD;/"^^,K3`OD
,6?8=GK6MPS?WDU!"
`
end
EOF
$ grep -I 8 test-file
Binary file test-file matches
$ grep --binary-files=without-match 8 test-file
Binary file test-file matches

Apparently, grep considers the file binary, but still does try to match and reports the results with it. Why is the "binary file" not ignored as the -I option prescribes?

I'm using GNU grep 3.1 on Ubuntu 18.04.

Best Answer

Looking at the grep manual, this seems to be because (bold mine):

If type is ‘without-match’, when grep discovers null input binary data it assumes that the rest of the file does not match; this is equivalent to the -I option.

However, grep also considers other data as indicating binary files:

Non-text bytes indicate binary data; these are either output bytes that are improperly encoded for the current locale (see Environment Variables), or null input bytes when the -z (--null-data) option is not given (see Other Options).

So the message won't be printed if:

  • the -I/--binary-files=without-match options are given
  • and the binary-ness is due to null bytes.

However, that's not the case with the example input. The example file is treated as binary because it doesn't fit the current locale (probably some UTF locale), not because it has null bytes. Otherwise:

% LC_ALL=C grep 8 test-file  
x���J�@`�y��
dIf��(��P������6u G7}S��8�0�&���'����9&�lL�Çl�t�y,蒩AU����F��cT�~
                                                                 �ʱ�k��]�Yx�$}�/����O�O�ù�4�����X��zd�Ȉ��W���,�2<�/�d�����+L
                                                                                                                            �Y�����7��PB

If I add a null byte to the file, grep fails successfully:

% printf '\0' >> test-file
% grep -I 8 test-file    
% echo $?
1
Related Question