grep --null

A few days ago a commit within OpenBSD caught my attention: what was this thing about --null flag in grap?
I am an avid user of grep, as many of us are when dealing with scripts and files and shells, however I was not aware of the --null feature. It turned out that GNU version of grep already has such feature, as well as the FreeBSD version, so OpenBSD here was simply catching up.
But what is all about? Well, sometimes you have filenames with a newline at the end.
Let’s not discuss about how terrible such an idea is…

grep without the --null

Here’s a simple example about the effects of having a newline at the end of the filename:

% cat << EOF >! "test.txt
"
Hello
World
EOF

test.c:    sprintf( database, "Hello World!");
test.txt
:World
test.z:world


As you can see, the test.txt filename ends with a \n newline character, so when we grep multiple files (hence grep has to print the matching line with the filename prefix), the name of test.txt makes the matching line to appear on the very new line (on the other hand, test.c works as expected).

grep --null

What is the effect of --null option? In order to better understand it, ask grep to give us only the list of files that do match:

% grep -i world -l  test.*
test.c
test.txt

test.z


In the output there is an extra new file due to the filename that ends with a newline. Now add the --null flag:

% grep -i world -l --null test.*
test.ctest.txt
test.z


The extra new line has disappeared, and now only the effective newline that is part of the filename is present. This is good to feed other beasts, like xargs

% grep -i world -l --null test.* | xargs -0 ls -s
4  test.c  4 'test.txt'$'\n'  4  test.z



that without the no-newline trick whould have been very confused in interpreting the filename:

% grep -i world -l  test.* | xargs  ls -s
ls: cannot access 'test.txt': No such file or directory
4 test.c  4 test.z



Why is named --null?

C developers mindset here: it appends a NULL string terminator at the end of the filename instead of the usual \n for a newline.
To some extent, this is the equivalent form of print0 in find.

The article grep --null has been posted by Luca Ferrari on June 30, 2022