Yahoo
Skip to main content
Advertisement
Advertisement
Advertisement
Advertisement

How I finally unlocked Linux’s find command

Linux mascot wearing sunglasses and using a laptop, surrounded by floating windows with the i3 Window Manager logo in the background.
Lucas Gouveia/How-To Geek

I've been using the find command for decades, but I never really understood it—until now. Forcing myself to follow through and finally crack this elusive command was the key to success.

Introducing the find command

The find command is one of the strangest Linux programs you'll use. It's essential enough to be omnipresent, yet obscure enough to be nobody's favorite. Alternatives like fd exist , but find is a lowest-common-denominator that works, just about.

In the simplest case, using find is a breeze :

This common type of query finds all files in the current directory or any directory below it that end with ".txt." If that's as far as you've ever got, you're probably unaware of just how complex find gets. Its man page has 1,639 lines (version 4.9.0), and once you dig into find, it starts looking less like a helpful utility and more like a full-blown programming language.

Advertisement
Advertisement

This complexity has always put me off in the past. I've long wanted a simple way to find files I've edited recently, but it's always evaded me. The results end up plagued with .git files or as an unsorted mess. So I decided to sit down and finally get to grips with find; the result was refreshing.

Basic usage of find looks like this:

Find then follows these steps to carry out its job:

  • Process each file and directory within starting-point; multiple starting points are supported.

  • Apply tests; if the file passes all of them, take action.

  • Act: the default action is -print, which prints the full file name.

Advertisement
Advertisement

A simple bare find, with no arguments, lists everything below the current directory:

A find command with no other arguments shows all files and directories below the current working directory.

This can be quite useful alone, but the real power of find comes with the tests and actions that it supports.

Getting find to report recently changed files

When you're working on a more complex task like this, it's a good idea to plan out what you need, then work out how to achieve it bit by bit. For the behavior I'm after, I know I need:

  • Files that I own.

  • Files that are not in hidden directories.

  • Results sorted by date, with the dates shown.

It's also useful to have some test data so you can check that your command does exactly what you want. In this case, I'm using the following file structure:

A file system tree showing a selection of files and directories, some hidden, one owned by another user.

Find files owned by a user

The first task is straightforward, thanks to find's -usertest, which only matches a file if the current user owns it:

USER is an environment variable that contains the username of the current user.

Advertisement
Advertisement

If you run the above, you may notice that the output contains directories:

A find command showing files (and directories) owned by the current user.

To ensure the final list only contains files, use find's -typetest. This takes a single character to denote the type of file to match: f for a regular file, d for a directory, and l for a symbolic link, among others:

At this point, find is reporting all files—not directories—owned by the current user:

A list of files owner by the current user.

Find files that aren't in hidden directories

The next part of the task is to stop find reporting files from hidden directories. The -prune action tells find to not descend into a matched directory:

The results from this command may seem strange at first, almost the opposite of what we want:

This is because of the way the prune action behaves, so here's what's going on:

Advertisement
Advertisement
  • The -path test matches all files (including directories) with a path that includes at least one hidden directory.

  • The -prune action prevents find from entering those directories.

  • Since there is no action other than -prune, find applies the -print action by default. This command is equivalent tofind . -path "*/.*/*" -prune -print.

Instead of printing the hidden directories that are pruned, though, you can print everything else using -o:

The -o operator is a logical OR, which means that find will match either the previous expression or the following one. So, if a path has a hidden directory, it will be pruned; otherwise it will be printed (an expression with no test will always match).

At this point, you can merge in the original expression that filtered by owner and file type:

This find command locates all the required files, and no more:

A find command correctly identifying files owned by the user, skipping files in hidden directories.

What remains is to sort them by most recently modified, and display that date alongside each file.

Advertisement
Advertisement

You can use the -path test to achieve the same results, with a slightly shorter command:

If you try this, you'll get the same results as the version that uses -prune. The difference is that -prune is more efficient because it will avoid testing files in hidden directories. If you're working with many directories, you should always use -prune to skip any you can avoid.

Sort results and print nicely

The find command doesn't handle sorting itself; for this task, you can usesort, one of the essential text processing commands . First, though, you'll need that modified date for each file. The -printf action tells find exactly how you want its output:

The -printf action will use the contents of the quoted string to format file information. In this example, %TY refers to the year of the last modified time. %Tm and %Td are the month and day, respectively, while %p is the file's name.

A find command showing four results, each of which includes a date and a path.

You can specify a more granular date for more accurate sorting, but I'm only really interested in dates, so the final step is to pipe to sort. Note that I'm ordering each line with the date first. This has two purposes: it keeps everything aligned nicely, but it also makes sorting a trivial task. Just pipe the results from find to sort:

Files from the find command piped to the sort command which orders them by date.
Advertisement
Advertisement
Mobilize your Website
View Site in Mobile | Classic
Share by: