Emptying a stubborn Trash

When Snow Leopard came out, one of the new features cited by Apple was the assistance it gives you when you want to eject a disk with a file that’s being used:

Snow Leopard improves the reliability of ejecting discs and external drives. Sometimes when an application or process is using the files on a drive, Mac OS X prevents you from ejecting it, but you don’t always know why. In Snow Leopard, you’ll get fewer of those errors and when you do get them, you’ll see exactly which application is using the drive, so you can quit it and eject the drive properly.

This is the kind of notice you get:

Oddly, Snow Leopard doesn’t give you the same kind of notice when it refuses to empty the Trash because one of its files is in use. I ran into this problem today. One of the files associated with BusyCal, which I had thrown away after testing, was still in use and keeping me from emptying my Trash.

For years, sites like MacOSXHints have published instructions on how to find the application or process that’s preventing disk ejection or Trash emptying. And although I’ve read those instructions many times, I could never remember the necessary command when I needed it.1 Until today.

The command is lsof, which is Unix for “list open files.” When called, it will list information about all the open files on your system. One of the pieces of information listed is the full pathname of the file and another is the program or process that’s using it.

I knew the file that wouldn’t leave the Trash was in a BusyCal.app subdirectory2, so at the Terminal, I typed

lsof | grep -i busy

Piping the results of lsof through grep filtered away everything except files or processes that included the string “busy.” The -i switch made the filtering case-insensitive. Here’s the output:

SystemUIS   146 drang  txt      REG       14,2    124408 26745933   /Users/drang/.Trash/BusyCal.app/Contents/PlugIns/BusyCalDockTile.docktileplugin/Contents/MacOS/BusyCalDockTile

This tells me that a process called SystemUIS (or a process whose first 9 characters are SystemUISlsof truncates the process name) is using a BusyCal file in my Trash. I opened the Activity monitor, located SystemUIServer, and quit it. It immediately restarted, but the new SystemUIServer process wasn’t using the BusyCal file, so I was allowed to empty the Trash.

A more generally useful command would grep for “Trash” to show the processes using any file in the Trash. I’ve turned this into a shell script called trash-users and put it in my $PATH.

echo "Looking..."
lsof | grep Trash

Because lsof can take a few seconds to run, I included the echo line to give some immediate feedback.

I don’t expect to use this command very often and will probably forget its name, but as long as I can remember it starts with trash I can rely on bash’s tab completion to fill in the remainder.

  1. There is always the rm command, but that’s the nuclear option. I’d rather deal with the process using the file than delete the file out from under it. 

  2. An application on the Mac is really just a directory (folder) with special features which make the Finder see it as a single file. The Unix command line, though sees it as a directory like any other.