Maciej Janicki's website

2019-07-27 shell fzf

Change to another shell's working directory

Today I’m going to share another trick for changing a shell’s working directory involving the fuzzy finder. Let us assume that you are doing something in a terminal and then need suddenly need another window for working in the same directory. There is an easy way to do this. It involves defining a function, which shows the current directories of all running shells in fzf, so that we can quickly choose one of them and navigate to it.

I’ll start by showing the full code of the function. Then, I’ll discuss it command by command.

choose_from_cwds() {
	for PROCID in $(pgrep "^$(basename $SHELL)$"); do
		readlink -e /proc/$PROCID/cwd
	done \
	| sort -u \
	| fzf --height=10
}

Of course, I refer to the function presented here by a handy alias:

alias chd='cd "$(choose_from_cwds)" && pwd'

Similarly to the function defined in the previous post, also the alias chd presents me with a fuzzy finder containing a list of directories. When I choose one of them, it navigates to it and displays the directory we’ve end up in.

So now let’s have a look at the commands used in the function.

pgrep "^$(basename $SHELL)$"

This gives us a list of PIDs of all running shell processes. The environment variable $SHELL contains the location of the binary running as shell (e.g. /bin/bash). We extract the name of the binary (bash) using the command basename. Be sure to enclose the name in ^$, so that pgrep does not match other processes whose commands accidentally contain this string.

readlink -e /proc/$PROCID/cwd

This is the most important line of the function: we use the PID of a shell’s process to find out its current working directory. Under Linux, this is very simple: the directory /proc/$PID contains various useful information about the process in question, which are served by the operating system as “files”. One of them is cwd, which is… simply a symbolic link to the process’s current directory! I can’t think of a simpler and more elegant way to expose such information - the beauty of Unix shows here.

We follow the link using the command readlink -e, which returns the path of the referred directory (and also ensures that it exists).

sort -u

Of course we may have multiple shells running with the same current directory. In this case, we don’t want to have multiple identical entries on our list, hence unique sort.

fzf --height=10

Finally, we pipe the list of directories to the fuzzy finder, which presents us with a neat chooser.