Jump around a filesystem with a bit of bash
(Banner remixed from images found on openclipart)
I've seen things like jump, which allow you to bookmark places on your system so that you can return to them faster. The trouble is, I keep forgetting to use it. I open the terminal and realise that I need to be in a specific directory, and forget to bookmark it once I cd
to it - or I forget that I bookmarked it and cd
my way there anyway :P
To solve the problem, I thought I'd try implementing my own simplified system, under the name teleport
, telepeek
, and telepick
. Obviously, we'll have to put these scripts in something like .bash_aliases
as functions - otherwise it won't cd
in the terminal itself. Let's start with teleport
:
function teleport() {
cd "$(find . -type d | grep -iP "$@" | head -n1)";
}
Not bad for a first attempt! Basically, it does a find
to list all the subdirectories in the current directory, filters the results with the specified regex, and changes directory to the first result returned. Here's an example of how it's used:
~ $ teleport 'pep.*mint'
~/Documents/code/some/path/pepperminty-wiki/ $
We can certainly improve it though. Let's start by removing that head
call:
function teleport() {
cd "$(find . -type d | grep -m1 -iP "$@")";
}
What about all those Permission denied
messages that pop up when you're jumping around places that you might not have permission to go everywhere? Let's suppress those too:
function teleport() {
cd "$(find . -type d 2>/dev/null | grep -m1 -iP "$@")";
}
Much better. With a teleport command in hand, it might be nice to inspect the list of directories the find
+ grep
combo finds. For that, let's invent a telepeek
variant:
function telepeek() {
find . -type d 2>/dev/null | grep -iP "$@" | less
}
Very cool. It doesn't have line numbers though, and they're useful. Let's fix that:
function telepeek() {
find . -type d 2>/dev/null | grep -iP "$@" | less -N
}
Better, but I'd prefer them to be highlighted so that I can tell them apart from the directory paths. For that, we've got to change our approach to the problem:
function telepeek() {
find . -type d 2>/dev/null | grep -iP "$@" | cat -n | sed 's/^[ 0-9]*[0-9]/\o033[34m&\o033[0m/' | less -R
}
By using a clever combination of cat -n
to add the line numbers and a strange sed
recipe (which I found in a comment on this Stack Overflow answer) to highlight the numbers themselves, we can get the result we want.
This telepeek
command has given me an idea. Why not ask for an index to jump to after going to the trouble of displaying line numbers and jump to that directory? Let's cook up a telepick
command!
function telepick() {
telepeek $1;
read -p "jump to index: " line_number;
cd "$(find . -type d 2>/dev/null | grep -iP "$@" | sed "${line_number}q;d")";
}
That wasn't too hard. By using a few different commands rather like lego bricks, we can very easily create something that does what we want with minimal effort. The read -p "jump to index: " line_number
bit fetches the index that the user wants to jump to, and sed
comes to the rescue again to pick out the line number we're interested in with sed "${line_number}q;d"
.
Update April 20th 2018: I've updated the approach here to support spaces everywhere by adding additional quotes, and utilising $@
instead of $1
.