The Unix find command is a versatile and powerful tool for developers, but can be complex to understand. In this article, I want to show you how I use it and some of the options that make it indispensable! Let's start with a basic command:
find . -name "Main*"
This command says:
1) find starting in this directory (".")
2) use the switch -name to find by name
3) find all files and directories that match "Main*"
What if you just want to find files? Easy enough, add the -type flag:
find . -type f -name "Main*"
Or just directories:
find . -type d -name "Main*"
Don't want to search all sub-directories? No problem, use maxdepth:
find . -type f -maxdepth 1 -name "*.java"
Running out of space on your computer? Use the find command to remove build artifacts... but be careful! Try it out on a test directory if you're not familiar with how this works. Java projects built with Maven use the target/ directory; here's how to clean them all up in a your home folder's "dev" directory (where I put my projects):
find ~/dev -name target -type d -exec rm -rf {} \; -print
Maybe you're a JavaScript developer and you discover that the various node_modules directories are taking up all your disk space:
find ~/dev -name node_modules -type d -exec rm -rf {} \; -print
The above two commands use "rm -rf" so BE CAREFUL
What if you need to find something inside of files? MacOS has a nice feature where you can do this from a Finder window, but you may be logged into a remote server. You can combine Unix commands in the find command to do this also. Here's a command to find everywhere you have "catch" in your code:
find ~/dev/myproject -name "*.java" -exec grep catch {} \; -print
Note that we'd added a "\;" and a "-print" at the end of this command. The first is to properly denote the end of the exec, the second is to print the found matching file, so you know which file matched (with full path).
So far, we've used the "-exec" option to run the "rm" and "grep" command. We can use any command with exec - you can use any command you like, just be careful that you escape using the chars within the command like you would for standard Unix CLI usage.
Do you need to find JAR files that are bigger than 1M in size? Find can help:
find . -type f -name "*.jar" -size +1M
The "type f" is a bit redundant here since we would not expect a directory to be named something like "file.jar"... but I like to get into the habit of specifying a directory or file when using the find command.
Which Java files have I modified in the last 6 days in the src/main directory?
find src/main -name "*.java" -mtime -5
There's much more to learn about the find command, and after using it forever I still learn something new often, so check out
the man page for the find command.
I hope you found this mini tutorial useful. If you're already using the find command, why not leave a comment below and share how you use it?
Discussion (2)
What does {} specify after the exec command?
The {} chars are substitution placeholders - basically means to place the found file (with full path) in that place. So if you run:
find . -name "*.java" -exec cat {}
And there's exactly two Java files under the current dir named "Main.java" and "DB.java", then this is what ultimately get executed:
cat src/main/java/Main.java
cat src/main/java/DB.java
Of course, if there are more .java files they would be found/matched then exec'd
HTH!