Mac OS X: The operation can’t be completed because the item is in use

Once in a while I can’t empty the trash because one file is in use. It doesn’t happen very often but once in a while. You then get such an error message:

trash file in use

When you then press continue all other files in the trash but this one file are removed. Mac OS X won’t let you delete this file as long as it’s in use. Unfortunately, it won’t tell you which program is using it.

There is an effective brute force method to solve the problem and a more elegant one. First the brute force method: You can delete the files in the trash from a terminal window. The trash is located in a .Trash folder in your user directory. You can get there with:

cd ~/.Trash

You will the file in there. You can just remove everything from the trash using:

rm -rf *

But you have to be careful. This command will delete everything recursively starting from the directory where you are. If you misspelled the directory and are not actually in the trash but in your user directory, it will delete many things you did not intend to delete. A solution for this problem is to combine the two commands above and only execute the second one if the first one was successfull. This is done combining them with &&:

cd ~/.Trash && rm -rf *

Of course deleting a file which is in use by a program might lead this problem to have an unpredictable behavior. So now to the more elegant solution. Instead of just deleting everything from the command line, we’ll first try to figure out which program is actually using the file. This is done using the lsof command:

Lsof lists on its standard output file information about files opened by processes.

It will basically return a list of all files (among other things) are opened by which process. We can then redirect the output to grep to filter by the file name which is in use (in my case some_file.mp4):

$ lsof | grep some_file.mp4
QuickTime 81275 henribenoit    5r     REG                1,2 192918592 32326555 /Users/henribenoit/.Trash/some_file.mp4

So now, you know it’s Quicktime. If the process name displayed in there is not so clear, you can get a full command line for the process which is preventing the file from being deleted. If you want to kill the process you can just use the commands at the end of this post. But I’d actually like to find out about the program and close it properly. This can be done by using the ps command:

$ ps 81275
  PID   TT  STAT      TIME COMMAND
81275   ??  S      0:58.83 /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player -psn_0_17662167

So we now we have the full command line (in this case it wasn’t required but does help in some cases). You can also combine the commands above into one with the same results:

$ ps `lsof | grep some_file.mp4 | awk ' { print $2; } '`
  PID   TT  STAT      TIME COMMAND
81275   ??  S      0:58.83 /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player -psn_0_17662167

If you ever get a command name for which you cannot find the corresponding program, you have two options: search for the parent process or just kill the process (note that wild process killing doesn’t really improve the stability of the system).

First we’ll lookup the parent process. This can be done using ps but we need to add the -f option to see the process ID of the parent process:

$ ps -f `lsof | grep some_file.mp4 | awk ' { print $2; } '`
  UID   PID  PPID   C STIME   TTY           TIME CMD
  501 81275   135   0  8:52PM ??         0:58.84 /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player -psn_0_17662167

The column PPID shows the parent process ID. Now we can use ps once again to get info about the process 135:

$ ps 135
  PID   TT  STAT      TIME COMMAND
  135   ??  Ss     0:16.98 /sbin/launchd

Of course in my case it’s not very interesting since the blocking process is an application so the parent is launchd. But in other cases, it might be useful. You can recurse until you find an applicaiton you acn close. If none of this work, you need to either force the deletion of the files as shown above or you need to kill the process:

$ kill 81275 && ps 81375
  PID   TT  STAT      TIME COMMAND

Now the blocking process is gone and you can fully empty the trash can. If the process doesn’t exit on kill, you should add the -9 option to force kill the process:

$ kill -9 81275 && ps 81375

Leave a Reply

Your email address will not be published. Required fields are marked *