Skip to content

Instantly share code, notes, and snippets.

@mbadran
Created June 16, 2009 01:30
Show Gist options
  • Save mbadran/130469 to your computer and use it in GitHub Desktop.
Save mbadran/130469 to your computer and use it in GitHub Desktop.
replace cd in bash to (silent) pushd
alias cd="pushd $@ > /dev/null"
@bobbydavid
Copy link

One annoyance with this alias is that simply typing "cd" will twiddle the directory stack instead of bringing you to your home directory.

@dideler
Copy link

dideler commented Mar 9, 2013

@bobbydavid makes a good point. This would be better as a function.

function cd {                                                                   
    if (("$#" > 0)); then
        pushd "$@" > /dev/null
    else
        cd $HOME
    fi
}

By the way, I found this gist by googling "silence pushd".

Copy link

ghost commented May 30, 2013

Don't you miss something?

function cd {
    if (("$#" > 0)); then
        if [ "$1" == "-" ]; then
            popd > /dev/null
        else
            pushd "$@" > /dev/null
        fi
    else
        cd $HOME
    fi
}

You can always mimic the "cd -" functionality by using pushd alone.
Btw, I also found this gist by googling "silent pushd" ;)

@cra
Copy link

cra commented Jul 1, 2014

And thanks to your last comment, I found this gist by googling "silent cd -" :)

@keltroth
Copy link

With bash completion activated a can't get rid of this error :
"bash: pushd: cd: No such file or directory"...

Any clue ?

@keltroth
Copy link

Got it !
One have to add :

complete -d cd

After making the alias !

My complete code here :

function _cd {
    if (("$#" > 0)); then
        if [ "$1" == "-" ]; then
            popd > /dev/null
        else
            pushd "$@" > /dev/null
        fi
    else
        cd $HOME
    fi
}

alias cd=_cd
complete -d cd

@jan-warchol
Copy link

I wanted to be able to go back by a given number of history items by typing cd -n, and I came up with this:

function _cd {
    # typing just `_cd` will take you $HOME ;)
    if [ "$1" == "" ]; then
        pushd "$HOME" > /dev/null

    # use `_cd -` to visit previous directory
    elif [ "$1" == "-" ]; then
        pushd $OLDPWD > /dev/null

    # use `_cd -n` to go n directories back in history
    elif [[ "$1" =~ ^-[0-9]+$ ]]; then
        for i in `seq 1 ${1/-/}`; do
            popd > /dev/null
        done

    # use `_cd -- <path>` if your path begins with a dash
    elif [ "$1" == "--" ]; then
        shift
        pushd -- "$@" > /dev/null

    # basic case: move to a dir and add it to history
    else
        pushd "$@" > /dev/null
    fi
}

# replace standard `cd` with enhanced version, ensure tab-completion works
alias cd=_cd
complete -d cd

I think you may find this interesting.

@3v1n0
Copy link

3v1n0 commented Oct 25, 2017

Another improvement over @jan-warchol version, to make cd - to alternatively use pushd $OLDPWD and popd depending on what we called before.

This allows to avoid to fill your history with elements when you often do cd -; cd - # repeated as long you want. This could be applied when using this alias also for $OLDPWD, but in that case it might be that you want it repeated there, so I didn't touch it.

Also added cd -l as alias for dir -v and use cd -g X to go to the Xth directory in your history (without popping, that's possible too of course, but it' something more an addition in this case).

# Replace cd with pushd https://gist.github.com/mbadran/130469
function push_cd() {
  # typing just `push_cd` will take you $HOME ;)
  if [ -z "$1" ]; then
    push_cd "$HOME"

  # use `push_cd -` to visit previous directory
  elif [ "$1" == "-" ]; then
    if [ "$(dirs -p | wc -l)" -gt 1 ]; then
      current_dir="$PWD"
      popd > /dev/null
      pushd -n $current_dir > /dev/null
    elif [ -n "$OLDPWD" ]; then
      push_cd $OLDPWD
    fi

  # use `push_cd -l` or `push_cd -s` to print current stack of folders
  elif [ "$1" == "-l" ] || [ "$1" == "-s" ]; then
    dirs -v

  # use `push_cd -l N` to go to the Nth directory in history (pushing)
  elif [ "$1" == "-g" ] && [[ "$2" =~ ^[0-9]+$ ]]; then
    indexed_path=$(dirs -p | sed -n $(($2+1))p)
    push_cd $indexed_path

  # use `push_cd +N` to go to the Nth directory in history (pushing)
  elif [[ "$1" =~ ^+[0-9]+$ ]]; then
    push_cd -g ${1/+/}

  # use `push_cd -N` to go n directories back in history
  elif [[ "$1" =~ ^-[0-9]+$ ]]; then
    for i in `seq 1 ${1/-/}`; do
      popd > /dev/null
    done

  # use `push_cd -- <path>` if your path begins with a dash
  elif [ "$1" == "--" ]; then
    shift
    pushd -- "$@" > /dev/null

    # basic case: move to a dir and add it to history
  else
    pushd "$@" > /dev/null

    if [ "$1" == "." ] || [ "$1" == "$PWD" ]; then
      popd -n > /dev/null
    fi
  fi

  if [ -n "$CD_SHOW_STACK" ]; then
    dirs -v
  fi
}

# replace standard `cd` with enhanced version, ensure tab-completion works
alias cd=push_cd
complete -d cd```

@juliyvchirkov
Copy link

juliyvchirkov commented May 31, 2021

brilliant thread, guys!

the last revision by @3v1n0 - it's true oldschool hell of shell programming, applause! 🎉🥁🎊

close to ideal, except one missing thing, the last one that matters - the special behaviour of cd -P

description from cd --help of bash builtin

-P use the physical directory structure without following symbolic links:

resolve symbolic links in DIR before processing instances of `..'

it's a pity, since I find this behaviour very useful for both interactive and scripted scenarios, and advise -P everyone - it even worth to be mentioned as alias cd='cd -P' at /etc/profile

however, as I see from your experiments above, one can try to mimic native cd -P behaviour like this - pushd "$(realpath "$1")" (nb! not tested)

if one implements this update during a week, that would be great! and I'll try to do it myself on weekends if not

@juliyvchirkov
Copy link

juliyvchirkov commented Jun 1, 2021

and one more note to catch up especially for mr. @keltroth and mr. @3v1n0

as it caught my eye, you both till the last revision leave $OLDPWD value unescaped, and it's quite dangerous, 'cause if the previous dir will include spaces in name - with cd - one will definitely fail to return. and since everything in this routine is silenced with /dev/null, it would be an adventure to find out what a hell is going on. been there, seen that

@juliyvchirkov
Copy link

juliyvchirkov commented Jun 1, 2021

I've been fond of tuning little things of that kind a lot, it's very exciting sometimes

the last for today - three more functions on topic from my own regular set of /etc/bash.functions

pushd () {
    builtin pushd ${1} >/dev/null 2>&1
}

popd () {
    builtin popd ${1} >/dev/null 2>&1
}

dirs () {
    builtin dirs -v
}

xterm

respect, guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment