Searching files and content with find and xargs
Showing all .txt
files with the word “foo” in them. Prepended with the filenames.
Usually I use grep
only with standard input but in this case we would lose the
file path if we did that. So xargs
to the rescue! It takes the output of the
previous command and add it to the last argument to the next. Beautiful and simple magic! 🔮
find / -name *.txt -print0 | xargs -0 grep -H "foo"
The -type f
is saying that we only want to search for regular files.
find . -type f -print0 | xargs -0 grep -H "foo"
Regular expression! Wanted to get some in here because it can be useful to filter the searched files.
find . -regex '.*/[a-z].txt' -print0 | xargs -0 grep -H "foo"
One thing to remember is that find
can use different regex dialects. On BSD OS’s (which macOS is a variation of) it by default uses the basic POSIX regular expression and the +
doesn’t work there. So you need to enable the extended POSIX regular expression by adding the option -E
. Check out regexp types reference.
find -E . -regex '.*/[0-9]+.jpg'
The above should match all files like 1.jpg
, 30.jpg
or 9999999.jpg
for that matter. The +
should make the preceding expression match one or more times. It works everywhere! But not on mac 💩. There is no--version
or -v
or anything to see which version it is. It obviously comes from some BSD
version (man find
says BSD General Commands Manual
). But which is a mystery for me.
Get rid of annoying error output
When you’re not root
and search the whole filesystem you will for sure get a lot of permission denied output which can be overwhelming. There’s a trick to get rid of that:
find / -regex '.*/[0-9]+.jpg' 2>/dev/null
As 2
is the Standard error
file descriptor, i.e., stderr
it will redirect all errors to /dev/null
which is a black hole where you never ever come back from if you get in 😱.
Read more about redirections of input/output here: http://mywiki.wooledge.org/BashGuide/InputAndOutput#File_Redirection-1