findr: a GNU/Unix ‘find’ helper

I’ve been more aggressive lately about creating helper scripts and aliases for common tasks, and I liked this find helper enough to want to share it. I find that I often do filename searches like this:

find -iname "*some_word*"

That’s not so bad to type, but why not make it even easier for my, and maybe your common usage? We might prefer to do something like this:

findr some_word

And assume that we’re looking for a case-insensitive, substring match. And since we love regular expressions, we can work with find’s regex options:

--regextype posix-egrep -iregex

Which is just begging for a helper to do the work for us in standard situations.

Before we look at the script and some examples, here are a few more considerations for our findr command:

  • With the -iregex option, the match is against the whole path, so we’ll wrap the supplied regex search term with dot-stars (.*) to loosen things up. We probably want to limit our match to the last item in the path: the filename or “leaf” dir, so it performs like a standard -name or -iname search. The second dot-star then becomes [^/]*, which says: don’t let a slash follow our search term.
  • For my find usage, I typically use the -mount option to not descend into directories on other file systems, so I’m making this the default, with a -a option to search “all” file systems. But of course your desires may differ.
  • It may be useful to have a “preview” option -p to show the find command that our script generates.
  • Our assumption will be that the last parameter is the regex search term.

findr.sh

(Use this code at your own risk, and use it however you like. To the extent possible, I’m putting this into the public domain.)

#!/bin/bash

 usage="\nfindr.sh: Helper to make regex find commands easier.\n\n"
usage+="  usage: findr.sh [-a] [-p preview mode] [find args] expression\n"
usage+="\t-a\tsearch all filesystems (default is -xdev/-mount)\n"
usage+="\t-p\tpreview mode; just show the resulting find command\n"
usage+="\n\t\t(can't combine params, e.g. -ap)\n"

preview=false
# use "nowarn" to avoid warning if -mount used after -type f, e.g.
xdev=" -nowarn -mount "

while [[ -n "$1" ]]; do
	if [[ $1 == "-h" || $1 == "--help" || $1 == "-help" ]]; then
		echo -e $usage
		exit 0
	elif [[ $1 == "-a" ]]; then
		xdev=""
	elif [[ $1 == "-p" ]]; then
		preview=true
	elif [[ $# -eq 1 ]]; then
		regex=$1
	else
		args+=" $1"
	fi
	shift
done

args+="${xdev}-regextype posix-egrep -iregex"
regex="^.*${regex}[^/]*$"

if [[ "$preview" == "true" ]]; then
	echo "find $args \"$regex\"" >&2
else
	find $args "$regex"
fi

I’ve created in ~/.bash_aliases:

  • alias findr='findr.sh'
  • alias findra='findr -a'

Thus:

findr secret-plans

Becomes:

find -nowarn -mount -regextype posix-egrep -iregex "^.*secret-plans[^/]*$"

You can add other “find” options, like the dir to search:

findr /home/scarpent secret-plans

Or specify the file type:

findr -type f secret-plans

Or whatever other option. The script includes the -nowarn option with -mount, because for example with this command:

find -type f -mount -regextype posix-egrep -iregex "^.*secret-plans[^/]*$"

find will complain about the order of options, and while I appreciate the good intentions and wisdom of the warning, it isn’t a problem for me. (Not until I get burned by missing some other suppressed warning, I guess.)

And you can take advantage of regular expressions! For example, maybe you want to look for the song “Oh, Yeah,” by Yello, and avoid matching on Elton John, Joni Mitchell, or Tony Orlando songs. You can use a word boundary:

findr "yello\b" or findr yello\\b

The find command is loaded with options and my understanding of it is only mildly nuanced, so this may (and will!) break down in many scenarios, but it’s not meant to be a replacement for direct use of find.

It’s just a helper, after all.

2 Comments

  1. Nice!

    I think “find” should have these defaults hard-wired with a switch, so “find -u whatever” (-u = “the usual”) worked like this.

  2. Thanks, Tony! I’m glad you liked it.

    It really is amazing how much stuff “find” can do — it’s a long process to learn it.

Comments are closed.