Find a file across entire file system

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the unix category.

Last Updated: 2024-11-21

I wanted to find all the .env files in the code dir on my system. What options are there?

Approach 1: Locate

The locate command is available on unix but with a bare-bones version on Mac.

When I ran

locate .env

It returned a bunch of files that were not called .env but just had env in their path, e.g.

/Library/Application Support/.../Applications/Max.app/.../Tools resources/M4L.envfol~.maxpat

It total I got about 490 files, which was far too many!

The man page online suggested some options like -basename, but these weren't supported on the macos version, so I downloaded the linux version (via brew install findutils). This installed a version of locate with g in front: glocate (to prevent clashes). It also installed a parallel to updatedb, called gupdatedb, which is the command build up the database. I wanted to index all files so I did sudo gupdatedb.

Afterwards I ran locate --basename .env. This returned 26 files and was lightning fast! However, none of them were the files I wanted... it seemed to be missing my code folder completely.

OK so I decided to try again, this time without sudo (in case it limits to current user) but also limiting indexing by excluding some unwanted system stuff

# Notice this is space separated
gupdatedb -prunepaths="/Applications /Library /System /Volumes"

With this DB generated I could do a regex search and filter to just .env files

glocate --regex '\.env$' |

This was pretty good and showed the files I wanted (with a small bit of node_modules crud that could be grepped away)

An interesting aside about locate: remember it is a cache, not a real-time search. Therefore results it shows may not actually exist if the DB was updated too long ago.

Approach 2: Find

I first tried find with the following node_modules ignore.

find . -name ".env" -and -not -path "node_modules"

However it return lots of entries in node_modules subdirectories

./node_modules/deeper/.env
./node_modules/.env

The fix was to remember that the path argument needs to fully match the path (rather than be a mere subset), therefore surrounding globs are needed.

find . -name ".env" -and -not -path "*node_modules*"

This worked great! A big advantage is that you can choose the starting directory, cutting out crud.

Approach 3: Rg

This is a standalone search tool written in Rust.

rg --no-ignore --color never --files --hidden ~/code | rg "\.env$"

Main learnings: