10 Tips for Using GNU Find

7114

The GNU find utility is one of the most useful commands you’ll ever get to know. At first glance the options and syntax can seem arcane. But, with a little practice, you’ll be able to locate any file on your system with almost no trouble at all. To help you get started, we’ve got 10 ways you can use find to get what you’re looking for.

Note that not all versions of find are created equal. The find command you’ll use on Linux is slightly different than the find on BSDs, Solaris, or Mac OS X. Much of the syntax is shared and can be used between systems, but not all.

Basic Use

Let’s start with the bare basics. If you’re looking to find a file and you know the name of that file — just not where you left it — then the syntax is simple. Just tell find to search for a specific name:

find -name filename

Assuming that filename exists, find will display the location of the file or files that match that name, like so:

 

jzb@kodos:~$ find -name filename
./projects/filename
jzb@kodos:~$

Finding Files by Size

Sometimes it’s useful to use other attributes to look for files. For instance, finding files by size. One good example, if you’re working with a server and notice that one of the partitions is beginning to fill up. Which file, or files, do you need to deal with? You can use find to look for files by size and then worry about how to make space.

Not surprisingly, the option to test by size is -size, followed by the size that you want to look for. You can use anything from blocks (b) to gigabytes (G). To find files that are 100k, you would run:

 

find -size 100k

That would find files that are 100k in size. That’s of limited use, though. To find files that are larger or smaller than an arbitrary size, use + or in addition to the number. So find -size +100k should return any files larger than 100k, and find -size -100k should return anything smaller.

You can also find files that are empty using the -empty test:

 

find -empty -type -f 

Note that I included an additional test for the type of file. Without that, find will include directories as “empty” files.

Finding Files by User

Another handy use of find is locating files by ownership, or even the lack of ownership. Let’s start with that. If you’ve been moving files around between systems, or if you’ve purged some users, you might have files that are orphaned. To find those, use:

 

find -nouser

To find files that are actually owned by a specific user, use the -user or -uid options. The -uid option will allow you to search by numeric user ID (UID), and -user allows you to search by user name or UID. So if I wanted to find all of my files in a directory, I’d use find -user jzb, or I could use find -user 1000 or find -uid 1000.

You might want to search for the files that are owned by user A or by user B. You can do this by adding the -o operator:

 

find -user root -o -user www-data

That will find all files that are owned by root or by www-data. If you want to find all files that aren’t owned by a user, you can use the -not operator:

 

find -not -user www-data

Of course the operators work with other options as well. You could choose to search for all files owned by a user that are not larger than a certain size, for instance:

 

find -user www-data -not -size +100k

Finding Files by Group

Another way you can search for files is by group, using the -group option. The -group option takes a group name or group ID (GID). The basic syntax is just find -group groupname.

Naturally, you can combine this with other operators. This might be useful if you’re trying to find all of the files owned by a certain user that are also owned by a particular group.

Finding by Permissions

You might occasionally want to check your filesystem for files that are world-writable or otherwise have the “wrong” permissions. The find utility supports this with several different options. The simplest are the -readable, -writable, and -executable operators. These check to see if the file is readable by the user running find. Note that these options are not available in older versions of find, so if your distro is a bit older you may not have those options.

Another option is to search by the file permission using -perm, which actually looks at the file’s mode. This way you can see if a file matches a specific set of permissions. For example, if you want to see what files are executable by the file’s owner and group, use:

 

find -type f -perm -110

The 110 tells find “look for files with the executable bit set for owner and group” and the tells find to ignore the other bits. That is, it’s OK if the file is also writable or readable, as long as the bits are set for it to be executable as well.

To restrict the search to only files that match the exact mode, don’t use the operator.

What if you want to find files that match the executable bit for owner or group? Instead of use /:

 

find -type f -perm /110

Any file that matches the group or owner permissions will match the search.

Searching by permission can be extremely useful but a little complex. It takes some time to get the syntax down, especially for users who aren’t already well-versed with the ownership modes. This is one where reading the man page is not just recommended, but essential.

Using Regular Expressions

Sometimes you’ll need to use regular expressions to match filenames. Naturally, find supports this — possibly more than you expect. Not only does find have regular expression support, it handles several different types of regex syntax. You can set the type using -regextype and one of the supported types like posix-awk, posix-egrep, and so on. See the man page for the supported types.

A quick example. Let’s say I wanted to find all files that have either a .php or a .js extension. I could run the following:

 

find -regextype posix-egrep -regex '.*(php|js)$'

That looks a bit complex, doesn’t it? Broken down it says to use the egrep syntax (-regextype posix-egrep) and then gives the regular expression to search for. The expression begins and ends with a single quote so that the shell won’t try to evaluate the regular expression itself. Then the .* expression is a wildcard that matches any character or characters. The (php|js) part says to look for php or js. The pipe (|) stands for “or” in that expression. Finally the dollar sign ($) that closes the expression says to look for those extensions at the end of a filename. So if you have a file that is named js.txt, it won’t match.

As with permissions, regular expressions can be complicated. We might just cover that topic in a future tutorial. But for now, see the man page for find and its documentation.

Working with Times

What if you want to find files by their age? This is something that can be useful if you’re trying to find a file that you know you created within a certain timeframe, or if you want to look for older files to delete. Lots of good reasons, actually.

The find utility is all about finding by time. You can search by access time (-atime) or the last time a file was modified (-mtime) or by the last time it was changed (-ctime).

For example, let’s look for any files that have not been modified in the last two days:

 

find -mtime +2

The options take a number that is interpreted as “n times 24 hours ago” and actually encompass a range. If you say +1, find will interpret that as “at least 24 hours ago, but not more than 48 hours ago.”

You can combine the options, if you want to look for files within a specific range. So find -mtime +2 -mtime -5 would be “two or more days ago, but not more than five days ago.”

Working with Minutes

Sometimes you need to look for files modified in the last day or so, and the previous options are a bit too broad for that. The good news is that find also has the -amin, -cmin, and -mmin, which are similar to the other options but they work with minutes rather than days. So if you want to look for something that was changed or accessed in the last day, you can use those options.

Limit Searches

Sometimes find provides more results than you need, or want. You can limit find results by using the -maxdepth option. For example, if you wanted to find every JavaScript file in your wordpress directory, you would use this:

 

find wordpress -name '*js'

But what if you only want to see if there are any JavaScript files in the top-level directory? You can limit that with -maxdepth:

 

find wordpress -maxdepth 1 -name '*js'

That will only search the wordpress directory, but not any of the subdirectories. Changing the -maxdepth to 2 would search subdirectories in the wordpress directory, but it would exclude their subdirectories.

Combining find with Other Commands

Now that you’ve found the files you’re looking for, what are you going to do with them? You can use find in conjunction with xargs or the -exec option to manipulate files after you’ve found what you’re looking for.

Say you want to change the ownership of a bunch of files from root to www-data. Finding all the files is only the first step; you also need to change the ownership. Doing it manually from a list of files returned by find sounds like tedium, and it is. So you might want to use the -exec option to change the ownership:

 

find -user root -exec chown www-data {} ;

That command tells find to pass all the files it finds to the chown utility and change the ownership to www-data. Piece of cake.

Summary

Knowing the find utility is a must for any Linux user who want to master their systems. You can get by without using find for typical desktop use, but for system administration you need to know your way around find. If you’re going to work with -exec and xargs to make changes to or remove files, you run a test or two first to ensure the command works as expected.

Have some find tips you’d like to share with the rest of the Linux.com community? Please share them in the comments.