Vim/Tmux – Find Which Vim/Tmux Has a File Open

open filesprocesstmuxvim

I use tmux at work as my IDE. I also run vim in a variety of tmux panes and will fairly often background the process (or alternatively I just close the window – I have vim configured not to remove open buffers when the window is closed). Now I've a problem, because a file that I want to edit is open in one of my other vim sessions but I don't know which one.

Is it possible to find out which one, without manually going through all my windows and panes? In my particular case, I know that I didn't edit it with vim ~/myfile.txt because ps aux | grep myfile.txt doesn't return anything.

Best Answer

It doesn't tell me everything, but I used fuser ~/.myfile.txt.swp which gave me the PID of the vim session. Running ps aux | grep <PID> I was able to find out which vim session I was using, which gave me a hint as to which window I had it open in.

Thanks to Giles's inspiration and a bit of persistence and luck, I came up with the following command:

⚘ (FNAME="/tmp/.fnord.txt.swp"; tmux switch -t $(tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index} #{pane_tty}' | grep $(ps -o tty= -p $(lsof -t $FNAME))$ | awk '{ print $1 }'))

To explain what this does:

(FNAME="/tmp/.fnord.txt.swp";

This creates a subshell and sets FNAME as an environment variable. It's not, strictly speaking, necessary - you could just replace $FNAME with the filename yourself, but it does make editing things easier. Now, working from the inside out:

lsof -t $FNAME

This produces only the PID of the process that has open the file.

ps -o tty= -p $(...)

This produces the pts of the PID that we found using lsof.

tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index} #{pane_tty}'

This produces a pane list of entries like session:0.1 /dev/pts/1. The first part is the format that tmux likes for targets, and the second part is the pts

| grep $(...)$

This filters our pane list - the trailing $ is so it will only match the one we care about. I discovered that quite by accident as I had pts/2 and pts/22, so there were two matches, whoops!

| awk '{ print $1 }'

This produces the session:0.1 part of the pane output, which is suitable for passing to tmux switch -t.

This should work across sessions as well as panes, bringing to focus the pane that contains your swap file.