#!/bin/bash SELF="$( basename $0 )" warn() { echo "$SELF: $*" 1>&2 } die() { echo "$SELF: fatal: $*" 1>&2 exit 1 } if [ "$1" = "-h" -o "$1" = "--help" -o "$2" != "" ]; then cat <} With no argument, $SELF searches for .*.swp files in the current directory. If only one is found, the PID of the process that owns it is redirected to the current TTY by running "reptyr ". If there are multiple .*.swp files, no process is redirected; instead the PIDs that own the files are printed to stderr. With a argument, the vim process editing that file (if any) is passed to reptyr. The can either be the actual file being edited, or the .*.swp file. Typical use case: you were editing a file remotely (via ssh), left yourself logged in and forgot to exit vim; now you're at the console or logged in from a different host and want to continue editing the same file. After "stealing" the vim process, it's best to write any changes and then exit vim immediately. To continue editing, run vim again. If you ignore this suggestion, things might or might not work OK depending on the terminal emulators in use, and/or the TERM setting. EOF fi [ "$( type -p reptyr )" = "" ] && \ die "reptyr not installed!" old="" for i in .*.swp; do [ ! -e "$i" ] && die "no .*.swp files" swppid="$( file $i | sed 's/.*, pid \([^,]*\),.*/\1/' )" # If there's an argument and we found the matching .swp, use it. if [ "$i" = "$1" -o "$i" = ".$1.swp" ]; then pid=$swppid break fi # If there's an argument and the current .swp file doesn't # match, ignore this .swp. [ "$1" != "" ] && continue # If the .swp's PID is no longer running, ignore it. if [ ! -d /proc/$swppid ]; then warn "$i: PID $swppid no longer running" continue fi # If we can't read the exe, it likely means it belongs to root, # or anyway not the current user. if [ ! -r /proc/$swppid/exe ]; then warn "$i: PID $swppid doesn't belong to user $( whoami )" continue fi # If the .swp's PID is running but it's not vim, the PID has been # reused. ignore it. This works even if vim was called by a # symlink (e.g. /usr/bin/vi => vim). case "$( realpath /proc/$swppid/exe )" in */vim) ;; *) warn "$i: PID $swppid not a vim process"; continue ;; esac pid=$swppid if [ "$old" != "" ] && [ "$pid" != "$old" ]; then die "multiple vim PIDs: $old $pid" exit 1 fi old=$pid done if [ "$pid" = "" ]; then msg="no vim PID found" [ "$1" != "" ] && msg+=" for $1" die $msg fi reptyr "$pid"