How to use FIND in Linux

With the right arguments, the FIND command is a powerful and flexible way to locate data on your system.
295 readers like this
295 readers like this
How to upgrade your Fedora Linux system with DNF

Opensource.com

In a recent Opensource.com article, Lewis Cowles introduced the find command.

find is one of the more powerful and flexible command-line programs in the daily toolbox, so it's worth spending a little more time on it.

At a minimum, find takes a path to find things. For example:

find /

will find (and print) every file on the system. And since everything is a file, you will get a lot of output to sort through. This probably doesn't help you find what you're looking for. You can change the path argument to narrow things down a bit, but it's still not really any more helpful than using the ls command. So you need to think about what you're trying to locate.

Perhaps you want to find all the JPEG files in your home directory. The -name argument allows you to restrict your results to files that match the given pattern.

find ~ -name '*jpg'

But wait! What if some of them have an uppercase extension? -iname is like -name, but it is case-insensitive.

find ~ -iname '*jpg'

Great! But the 8.3 name scheme is so 1985. Some of the pictures might have a .jpeg extension. Fortunately, we can combine patterns with an "or," represented by -o.

find ~ ( -iname 'jpeg' -o -iname 'jpg' )

We're getting closer. But what if you have some directories that end in jpg? (Why you named a directory bucketofjpg instead of pictures is beyond me.) We can modify our command with the -type argument to look only for files.

find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f

Or maybe you'd like to find those oddly named directories so you can rename them later:

find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type d

It turns out you've been taking a lot of pictures lately, so let's narrow this down to files that have changed in the last week.

find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f -mtime -7

You can do time filters based on file status change time (ctime), modification time (mtime), or access time (atime). These are in days, so if you want finer-grained control, you can express it in minutes instead (cmin, mmin, and amin, respectively). Unless you know exactly the time you want, you'll probably prefix the number with + (more than) or (less than).

But maybe you don't care about your pictures. Maybe you're running out of disk space, so you want to find all the gigantic (let's define that as "greater than 1 gigabyte") files in the log directory:

find /var/log -size +1G

Or maybe you want to find all the files owned by bcotton in /data:

find /data -owner bcotton

You can also look for files based on permissions. Perhaps you want to find all the world-readable files in your home directory to make sure you're not oversharing.

find ~ -perm -o=r

This post only scratches the surface of what find can do. Combining tests with Boolean logic can give you incredible flexibility to find exactly the files you're looking for. And with arguments like -exec or -delete, you can have find take action on what it... finds. Have any favorite find expressions? Share them in the comments!

Tags
Ben Cotton is a meteorologist by training, but weather makes a great hobby. Ben works as the Fedora Program Manager at Red Hat. He co-founded a local open source meetup group, and is a member of the Open Source Initiative and a supporter of Software Freedom Conservancy. Find him on Twitter (@FunnelFiasco) or at FunnelFiasco.com.

12 Comments

Thanks for writing this article, Ben. The find command has always perplexed me a bit (well, a little more than a bit). This article clears everything up.

Glad you liked it, Scott. `find` is like an onion: there's always another layer to peel back and discover. And if you're not careful, it can make you cry.

In reply to by Scott Nesbitt

$ find ~ ( -iname 'jpeg' -o -iname 'jpg' )
bash: syntax error near unexpected token `('

Any idea what's wrong here? Doesn't work with " either.

Also, your website is not accepting email addreses that end with caramail.fr. That's just dandy.

You need to escape the parentheses with backslashes, otherwise the shell try to interpret it as a command group to run in a subshell.

I'll let the site admins know about the email domain issue. Thanks for letting us know.

In reply to by student (not verified)

Thanks Ben, that does work. I see you updated the article.

The problem was in having a space behind my email address which caused it to be marked as invalid. Took me a while to figure out. Removing the space allowed me to post. ;)

In reply to by Ben Cotton

Hi student,

I think the email is being blocked because our Drupal platform doesn't recognize it as a standard email format. I'll look into this and see if that is, in fact, the case here.

Jason

In reply to by student (not verified)

Thanks for the Link Ben, and the follow up. I Use find for so much, I hope we can help convert people to Linux and the Find command vs some of the awful GUI experiences I've had.

Excellent article, Ben! I use find a lot in conjunction with grep, for example:

find . -name \*.java -exec grep -l System.err {} \; -print

will list all the *.java file names that contain the string System.err

My favorite find expression is when I combine it with grep(1) as follows:
$ grep "aWord" `find . -name "*.c"`

Also I always used the "find ... -exec grep ..." method to do a recursive search but it doesn't show you the filenames. Which you can fix by doing "... grep aWord {} /dev/null \;". But Mihalis' method of "grep aWord `find . -name \*.txt` is much shorter way to achieve the same.

The exception being when one or more filenames contain spaces. In that case "find ... -exec grep ..." will work while "grep ... `find ...`" will fail. Interesting !!

In reply to by Mihalis Tsoukalos

Willem, you can see the filenames with the find... -exec grep ... by appending "-print" to the command. If the "-exec grep" part succeeds, the "-print" part causes the name of the file to be printed.

In reply to by Willem van Schaik (not verified)

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.