DEV Community

Bash: How To Teleport In The Terminal

Jimmy McBride on July 02, 2020

Overview Today, I'm going to be sharing a little trick I use to teleport around my terminal with ease. Do you change to your project d...
Collapse
 
kenbellows profile image
Ken Bellows • Edited

pushd and popd are super handy for jumping to several locations, then trying to backtrack to where you were a few jumps ago; I've known about them for a while and still haven't gotten into the habit of using them.

But for simple one-off cases, just jumping to one directory and the jumping back to the last one, there's another option that I use more often: if you call the cd command with the - character, it jumps back one directory!

> ~/projects/my-thing/src
$ cd ../../my-other-thing/sec

> ~/projects/my-other-thing/src
$ cd -

> ~/projects/my-thing/src
$ 

This only works for a single level; whereas pushd/popd will store as many moves as you want, if you issue cd - a bunch of times, you'll just jump back and forth between the same two directories. But for most of my own day to day uses, it gets the job done. This is especially handy when you weren't planning to jump back, like when you misremember where something is and you cd to the wrong place, then want to jump back to where you were.

Another related protip: the git checkout command adopted the same convention, so that git checkout - will checkout out the previous branch!

Collapse
 
cmbell715 profile image
Colin

~- is the value of the shell variable OLDPWD, so you can list out your previous directory with ls ~- . Saves a little time from having to type all the extra characters in cd - && ls && cd - .

But since it holds the actual directory path, it's even more useful because you can quickly list out any subdirs with ls ~-/oldPwdSubDir/anotherSubdir

Collapse
 
dom111 profile image
Dom Hastings • Edited

Another useful feature of cd, calling it with no arguments takes you to ~. This can save you doing cd ../../../.. or cd ~!

Collapse
 
kenbellows profile image
Ken Bellows • Edited

A side effect of this that sometimes catches me off guard is that if you try to cd to an environment variable that doesn't exist, or if you misspell a variable (e.g. cd $PORJ_HOME instead of $PROJ_HOME), you end up running plain cd by accident and going home instead! Always takes me a second to realize what happened

Collapse
 
fwolfst profile image
Felix Wolfsteller

Maybe worthwile to note that zsh gives you multiple cd - entries and you can even iterate and inspect the list when hitting tab. Quite nice. And then wd plugin for "warp points" (basically cd X aliases, but with convention).

Collapse
 
waylonwalker profile image
Waylon Walker

I ❤️ aliases

You gotta check out rupa/z. It's not quite as reliable as an alias, it is magical. It's based on your frecently used directories.

GitHub logo rupa / z

z - jump around

Z(1)                             User Commands                            Z(1)
NAME
       z - jump around
SYNOPSIS
       z [-chlrtx] [regex1 regex2 ... regexn]
AVAILABILITY
       bash, zsh

DESCRIPTION
       Tracks your most used directories, based on 'frecency'.

       After  a  short  learning  phase, z will take you to the most 'frecent'
       directory that matches ALL of the regexes given on the command line, in
       order.

       For example, z foo bar would match /foo/bar but not /bar/foo.

OPTIONS
       -c     restrict matches to subdirectories of the current directory

       -e     echo the best match, don't cd

       -h     show a brief help message

       -l     list only

       -r     match by rank only

       -t     match by recent access only

       -x     remove the current directory from the datafile

EXAMPLES
       z foo         cd to most frecent dir matching foo

       z foo bar     cd to most frecent dir matching foo, then bar

       z -r foo      cd to highest ranked dir matching foo

       z -t foo      cd to most recently
Collapse
 
i5513 profile image
i5513

I was hopping to see this kind of tools at this post

Collapse
 
ecognito profile image
E Cognito • Edited

I use a combination of z and aliases. E.g.:

alias projects="z ~/Documents/projects"

So now, if I just type projects I'll always go to the ~/Documents/projects folder, but if I type projects img I'll have a good chance of going to the ~/Documents/projects/static/img folder.

The alias is using z, but only to change to a folder under ~/Documents/projects.

Collapse
 
tchoupinax profile image
Tchoupinax

Otherwise, you could use a better z :)
github.com/ajeetdsouza/zoxide

Collapse
 
samuelabreu profile image
Samuel Abreu

One extra of using &&, if the first command fails it stops, if you need to run all commands even when any of them returns an error you can use ;

As && you also can use ||, to execute something if the previous command returns an error, very handy on scripts, something like:

command > /dev/null 2>&1 || exit 1

To suppress stdou and stderr of command but stop the script if returns an error

Collapse
 
jimmymcbride profile image
Jimmy McBride

That's actually really useful to know! Thanks for sharing!

Collapse
 
bloodgain profile image
Cliff

I've never gotten into the habit of using aliases for cd-ing into directories, but I use the pushd set of commands so much, I have them shortened to pu, po, and ds (for dirs -v). I don't personally have a huge use for location aliases, as I just use soft links to create shortcuts to them from my home directory. Typing ~/ isn't a huge deal to me.

That said, the "proper" or POSIX-y way to do this is to use the CDPATH variable. Much like you can set your default binary paths with the PATH variable, you can give cd a list of places to look for directories you've asked for. You should usually make . the first directory in CDPATH, but you can add as many additional directories as you like. So in your examples, if you add ~/Documents to your CDPATH, you could get to your projects folder by just typing cd projects from wherever you were. As long as the current directory didn't contain a "projects" folder, you'd be taken to your folder at ~/Documents/projects. The pushd command should obey the CDPATH as well, but I haven't tested it in a while.

Collapse
 
vavrikvladimir profile image
Vladimir

Hello Jimmy,
thanks for article.
Please check the code in the CD Aliases section. There are missing the &&.
The correct code should be:

alias ..="cd .. && clear && ls"
alias ...="cd ../.. && clear && ls"
alias ....="cd ../../.. && clear && ls"
alias ....="cd ../../../.. && clear && ls"
Collapse
 
jimmymcbride profile image
Jimmy McBride

Thank you very much! Good catch. The changes are saved now. :)

Collapse
 
mehuge profile image
Mehuge

Supercharge your cd command with something like this:

function goto() { eval "$(~/bin/goto "$@")"; clear; ls; }

Then in ~/bin/goto you can put extended logic that will find where you want to go, for example

#!/bin/bash
GO() {
  if test -d "$1" ; then
    echo "builtin cd $1";
    exit 0;
  fi
}

case "$1" in
somehost) echo "ssh adf@somehost.somedomain.com" ; exit 0 ;;
work) echo "builtin cd /path/to/work/Projects"; exit 0 ;;
esac

GO "$HOME/$1"
GO "/d/dev/$1"
GO "/c/GAMES/$1"

exit 0

Finally, if you prefer to use cd rather than goto add an extra alias:

alias cd=goto

Example Usage:

cd somehost
cd myproject
Collapse
 
selim13 profile image
Dmitry Seleznyov

For entering frequently visited directories I really enjoy combination of

  • z frequently visited directories tracker
  • fzf command line fuzzy finder
  • fzf-z plugin that combines the above

Then CTRL-G dev will show me the list of all most used directories with dev in their name sorted by the usage frequency. Hitting enter with enter the directory.

Collapse
 
andyanderson profile image
Andy Anderson

Great idea, Jimmy! I’ve used aliases with pushd/popd for decades, actually, but never thought to include an automatic ls on the end. For example:

alias ,=pushd

This uses one other nice feature of pushd — by itself it swaps the top two items on the directory stack! So you can quickly go back and forth between two directories with a single comma.

Including && ls at the end of this, though, prevents applying it in general, as any trailing file/directory arguments are picked up by the ls. But if you instead use a shell function:

function , { pushd $1 && clear && ls; }

it works both with and without an argument.

Also, if you don’t mind occasionally typing out source, you can repurpose . :

alias .=popd

I’m using . here because it’s next to ,, it signals finality, and there really aren’t any other punctuation keys available without shift that aren’t interpreted by the shell for something else 😀

I really like the .. idea, though I doubt I would use more than one level very often. One other suggestion I would make is to perhaps provide a variant,

alias ,,="pushd .. && clear && ls"

to add the parent directory to the directory stack.

Finally, sometimes I want to remind myself of the current directory stack, which is displayed with dirs. Again, being short on punctuation keys but given this is not that common, I can alias it to ,., which is in keeping with the rest of these options:

alias ,.=dirs
Collapse
 
alexmartelli profile image
Alex Martelli

A small typo in:
alias ..="cd .. && clear && ls"
alias ...="cd ../.. && clear && ls"
alias ....="cd ../../.. && clear && ls"
alias ....="cd ../../../.. && clear && ls"
the 4th alias is identical to the 3rd one, so will over-write it; I imagine you meant the 4th alias to be five dots, not just four like the 3rd one.

Collapse
 
jimmymcbride profile image
Jimmy McBride

Fixed! Thank you!

Collapse
 
rrei profile image
Rui Rei

Good post :)

While I recognize the value in setting up custom aliases, IMHO, fzf (github.com/junegunn/fzf) is all I need. I can type like a raging lunatic monkey and most of the time it still guesses what I actually wanted to type. fzf changed my life!

Collapse
 
teraspora profile image
John Lynch

Make aliases more easily:

#!/bin/bash
# Quickly make a persistent alias
echo "alias $1='$2'" >> ~/.bash_aliases
. ~/.bash_aliases
Collapse
 
jimmymcbride profile image
Jimmy McBride

This is leet af! I'm stealing this for sure.

Collapse
 
gabrielizalo profile image
Gabriel Porras

These are my aliases and adding yours... Very cool recommendations. Thanks

alias la="ls -lart"  or  la="ls -lrt"
alias e="exit"
Enter fullscreen mode Exit fullscreen mode
Collapse
 
bew profile image
Benoit de Chezelles

Hey, instead of typing e or exit, you can do Ctrl-d, it will do the same as exit in almost all cli apps!

Basically Ctrl-d sends a special control character to the application, saying "there is nothing left to read!" which will usually close the cli app.

Collapse
 
antoniogamiz profile image
Antonio

Greaaaaaaat!!!! pushd is just amazing! I will miss typing cd on my terminal from now on. Thanks!

Collapse
 
piyushkmr profile image
Piyush Kumar Baliyan

I love aliases, laziness converted to productivity hacks.
Here is my implementation of common git shortcuts, along with some common patterns using bash functions.

Collapse
 
jimmymcbride profile image
Jimmy McBride

I didn't know you could do git aliases like that. Really cool stuff. Thanks for sharing! 🔥

Collapse
 
mallowigi profile image
Elior Boukhobza

I've been using autojump for mac/unix for a while now. Just using j <part of the dir> and it "teleports" you automatically to your last recent places. The only thing needed is to cd at least once to the repository.

Collapse
 
stephencweiss profile image
Stephen Charles Weiss

I have this little function in my .zshrc which is pretty convenient:

# up is a composable version of 'cd ..' taking a numeric argument. if one is passed (e.g., `up 3`, the result is `cd ../../../`)
# taken from here: https://news.ycombinator.com/item?id=9869231
function up {
        if [[ "$#" < 1 ]] ; then
            cd ..
        else
            CDSTR=""
            for i in {1..$1} ; do
                CDSTR="../$CDSTR"
            done
            cd $CDSTR
        fi
    }
Collapse
 
johnbetong profile image
John Betong

My favourite is the humble *

instead of:
cd /var/www/this-is-a-test-to-see-if-it-works.tk
pwd
$ /var/www/this-is-a-test-to-see-if-it-works.tk

try this instead:
cd /var/www/this-*
pwd
$ /var/www/this-is-a-test-to-see-if-it-works.tk

Collapse
 
bimlas profile image
bimlas

This shell script could be handy if you want to jump to a specified directory to execute only a single command: github.com/bimlas/bash-mosh

For developers who running the same command in different directories repeatedly, Mosh is a productivity tool that saves time by executing the command without having to change the directory. Unlike other similar tools, Mosh does not bound to a certain software (like Git for example), it can execute any shell command. It works on any Bash-compitable shell (Bash, Zsh, Git Bash on Windows, etc.).

Collapse
 
mateus_vahl profile image
Mateus Vahl

If you are using ohmyszsh: github.com/ohmyzsh/ohmyzsh/tree/ma...
pj my-project for opening my-project
pjo my-project for open the project with yout $EDITOR

Collapse
 
cbloss profile image
cbloss

Had no idea about &&! Great tip. Thanks!

Collapse
 
kmacedovarela profile image
Karina Macedo Varela

Lovely tips, thanks a lot!

Collapse
 
bulletmark profile image
Mark Blakeney

More than 10 years ago I wrote github.com/bulletmark/cdhist which I use probably 100 times per day. I don't know how the rest of you get by without it!

Collapse
 
bartoszwolinskiingeniousio profile image
Bartosz-Wolinski-IngeniousIO • Edited

Great article!
But I still prefer using Autojump github.com/wting/autojump

Collapse
 
tanghoong profile image
tanghoong

Few of the aliases i always use navigate between sub dir...
.1= ..
.2=../..
.3=../../..
.4=../../../..
.5=../../../../..

Collapse
 
cocoonkid profile image
cocoonkid

I use github.com/b4b4r07/enhancd and never looked back..

Collapse
 
sinewalker profile image
Mike Lockhart

I use a combo of ..... aliases and $CDPATH together with bash TAB completion. Put common project roots into CDPATH

Collapse
 
rkb profile image
Robert K. Bell

What if I don't want to write & maintain the aliases?

That's where autojump comes in.

(same niche as rupa/z?)