Search code examples
bashgrepfindnull-character

Trying to grep a find -print0 causes strange behavior


I have a folder full of directories/files with spaces in their names, and I want to copy all of the *.ttf files to another directory except for the folders Consolas and System Volume Information. Following this post, I tried:

find ... -print0  | grep -v "System Volume Information" --null | grep -v "Consolas" --null | xargs -0 cp -t destination

For some reason, this results in a Binary file (standard input) matches message from the first grep. Using egrep to combine the filters, I attempted:

find . -name '*.ttf' -print0 | egrep -v "(System Volume Information)|(Consolas)" --null | xargs...

But in this case, egrep will print out nothing to the terminal, even though there are plenty of other folders besides System Volume Information and Consolas. When I removed all but the find part of the command, I got one large chunk of text with no newlines, because of the -print0 option. Since the whole block included Consolas, by omitting it I was omitting everything. I confirmed this when I tried doing a grep Arial on the results and the whole block was printed out.

How should I prevent this behavior in grep?


Solution

  • This is expected behavior of using '-v' option of grep. It's doing what your telling it to by not giving you any lines that contain Consolas. To avoid this don't use -print0 and post process with xargs (as you've already discovered) or if you really needed to run everything together do it after the 'grep -v' filters via something like this:

    echo -n $(find . -name '*.ttf' | grep -v "System Volume Information" --null | grep -v "Consolas" --null)

    but you probably don't need that for this problem as xargs is sufficient.