KISS

Keep It Simple Stupid

Enabling locate on OSX

| comments

locate is a nice tool to quickly find files by name because it builds a database of all files and searches it instead of the filesystem. I know OSX has Spotlight, but it’s graphical, has some indexing issues sometimes, and the command-line client is clumsy. I prefer simpler UNIX tools. Some more info in the Arch wiki.

I’m mostly interested in locating my own files, so the database will be stored in the home directory and updated from my user, not root.

I’m using glocate (GNU locate) from the findutils brew package because it’s newer and has more features:

1
$ brew install findutils

We can update the database manually like this:

1
$ gupdatedb --prunepaths=/Volumes --output=$HOME/locatedb

It will print multiple “Permission denied” errors because some directories are accessible only by root.

Then I have the following in my ~/.zshrc to use it with my local database:

1
2
3
4
if which glocate > /dev/null; then
  alias locate=glocate
  [[ -f "$HOME/locatedb" ]] && export LOCATE_PATH="$HOME/locatedb"
fi

The important step here is to setup periodic automatic database updates, which we can do with such a file placed in ~/Library/LaunchAgents/:

Launch agent to update locatedb periodically (user.updatedb.plist) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>user.updatedb</string>
  <key>LowPriorityIO</key>
  <true/>
  <key>Nice</key>
  <integer>13</integer>
  <key>ProgramArguments</key>
  <array>
      <string>sh</string>
      <string>-c</string>
      <string>date; /usr/local/bin/gupdatedb --prunepaths=/Volumes --output=$HOME/locatedb 2&gt;/dev/null</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>StandardErrorPath</key>
  <string>/tmp/updatedb.err</string>
  <key>StandardOutPath</key>
  <string>/tmp/updatedb.out</string>
  <key>StartInterval</key>
  <integer>86400</integer>
</dict>
</plist>

It will run gupdatedb with a low priority when you load it and then every 24 hours (86400 seconds). It prints the start date just so that I can verify the service works by checking the /tmp/updatedb.out file. Load it with:

1
$ launchctl load ~/Library/LaunchAgents/user.updatedb.plist

After some time you can see the results:

1
2
3
4
5
6
7
8
9
$ ll locatedb
-rw-r--r--  1 user  staff  52196031 Apr 18 12:25 locatedb
$ cat /tmp/updatedb.out
Sat Apr 18 12:21:28 EEST 2020

$ locate .zshrc
/Applications/AppCode.app/Contents/plugins/terminal/.zshrc
/Users/user/.zshrc
/Users/user/.zshrc.swp

Comments