40

I'm dealing with java projects which often result in deeply nested folders (/path/to/project/com/java/lang/whatever, etc) and sometimes want to be able to jump, say, 4 directory levels upwards. Typing cd ../../../.. is a pain, and I don't want to symlink. Is there some flag to cd that lets you go up multiple directory levels (in my head, it would be something like cd -u 4)? Unfortunately I can't find any man page for cd specifically, instead just getting the useless "builtins" page.

  • 1
    Modifying bash to interpret cd ... where the number of '.' would be the number of levels to go up. Would this cause a conflict that I'm not aware of? – user48420 Apr 19 '16 at 17:48
  • For those coming here for MacOS you can install zsh and Oh My Zsh which is a better alternative to bash and then you can just do cd ... (multiple dots) like it should be – Dominic Jun 9 '19 at 13:11

14 Answers 14

31

A simple function, with an alias, too:

function cd_up() {
  cd $(printf "%0.s../" $(seq 1 $1 ));
}
alias 'cd..'='cd_up'

(You could define this in ~/.bashrc if you want it in every instance).

It's simple to use:

$ cd.. 10
| improve this answer | |
  • Nice one! Works for me! Bash 4.3.11 – Carlos Nunez Sep 18 '15 at 18:29
  • 2
    Good answer; you might want to point out that this is better than solutions such as eval $(printf "cd ..;%.s" $(seq $1)) which cd multiple times, because ~- aka $OLDPWD is set to the working directory from before invocation, rather than to an intermediate directory. P.S. - it simplifies to cd $(printf %.s../ $(seq "$1")) if you want. – Toby Speight Mar 15 '17 at 13:45
30

Or... try this: (yay Google)

Navigate up the directory using ..n :

In the example below, ..4 is used to go up 4 directory level, ..3 to go up 3 directory level, ..2 to go up 2 directory level.

Add the following alias to the .bash_profile and re-login.

alias ..="cd .."

alias ..2="cd ../.."

alias ..3="cd ../../.."

(etc)

See Hack #2

| improve this answer | |
  • 11
    I would rather use the aliases .., ... and .... as they are faster to type, but the principle of aliases is the same of course. – Bernhard Jul 16 '12 at 20:24
  • 1
    @bernhard You're more than welcome to, as I don't believe it would cause any conflicts. I just left it as-is because I quoted it from the website. – cutrightjm Jul 16 '12 at 20:25
  • The 4DOS.EXE shell for DOS also supported cd ..., cd .... etc. It was very handy. – Alexios Jul 25 '13 at 21:43
  • 1
    ..... is not faster than ..4 , in fact it is 2 characters slower.. – Ryan Oct 11 '19 at 13:49
  • I would argue that .... is faster than ..3, since it's a repeated keystroke. And I'm not likely to navigate up more than 3 directories at a time. In fact, I normally only use .. or ..., since I can't mentally walk my file system in jumps of 3 or more. – Cameron Bieganek Jan 13 at 16:36
10

A simple, low-tech solution that doesn't need any setup. Only works in shells with bash-style command editing, though.

  • Type cd ..
  • Press Up-arrow Return as many times as needed. Very fast if you use two fingers.
| improve this answer | |
  • 2
    haha, not a bad answer i guess :) – joshmcode Apr 6 '18 at 19:52
8

Turns out the correct answer is 'cd +n', where n is the number of levels you want to go up. Too bad this isn't documented anywhere!

| improve this answer | |
  • 18
    at least it does NOT work in bash. – HongboZhu Mar 26 '13 at 15:32
  • 5
    Doesn't work on bash 4.2.25 as shipped with Debian. Out of curiosity, what *nix and/or shell are you using? – Alexios Jul 25 '13 at 21:44
  • Bash has a built-in called dirs that takes [+n] as an argument, and prints the nth unique directory that was added via pushd. If you alias cd to pushd, then you can use this. However, note that this is not technically an answer to the OP's question, because this has to do with unique directories, meaning that the order gets messed up over time, as you return to the same directories. – Brian Peterson Oct 15 '13 at 18:07
  • Yeah, pushd and popd also take a [+n] option, which is why that is able to work. Also, though it's imperfect and indirect, I guess this can be used as an answer to the question. Often you visited the directories above you recently, so they will be in the last 10 dirs stored by the directory stack. – Brian Peterson Oct 15 '13 at 18:15
  • did not work for me... – Vass Sep 23 '16 at 0:31
4

You could write a function (it has to be a function, as you want to change the state of your shell itself, namely the working directory; an external command would affect only its own process).

Here's a function that will go up a number of levels passed as argument (default 1) in the physical directory structure (so, like cd -P .., n times):

up() {
    # default parameter to 1 if non provided
    declare -i d=${@:-1}
    # ensure given parameter is non-negative. Print error and return if it is
    (( $d < 0 )) && (>&2 echo "up: Error: negative value provided") && return 1;
    # remove last d directories from pwd, append "/" in case result is empty
    cd "$(pwd | sed -E 's;(/[^/]*){0,'$d'}$;;')/";
}

Use it like this:

up 4
| improve this answer | |
  • 1
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – Donald Duck Mar 13 '17 at 16:01
  • 1
    Agreed, I have added a few comments to help. – mgild Mar 13 '17 at 19:11
  • To be nitpicky, isn't up 4 really equivalent to cd /some/dir/ assuming $PWD = "/some/dir/that/is/deeply/nested/"? – snapfractalpop Aug 15 '18 at 23:28
2

Not exactly what you're asking for but you should look into pushd and popd. I find them much more useful for folder navigation than some cd... alias

If you're going back and forth from a couple fixed areas, the usual thing is to have aliases.

alias proj1='cd /some/dir/containing/proj1'
alias proj2='cd /some/deeper/dir/structure/containing/proj2'
| improve this answer | |
1

Instead of using aliases you could also use the following bash function:

function mcd() {
  up=""

  for ((i=1; i<=$1;i++)); do
    up="${up}../"
  done

  cd $up
}

(or as a one-liner: function mcd() { up=""; for ((i=1; i<=$1;i++)); do up="${up}../"; done; cd $up; })

Adding this to your ~/.bashrc file will make it available in your terminal and the building of a String ../../../../../../ before calling cd will also make it possible to use cd - to jump back to the start directory.

A more helpful implementation could also contain some user-input checks:

function mcd() {
    if [[ $1 -lt 1 ]]; then
        echo "Only positive integer values larger than 1 are allowed!" >&2
        echo -e "\n\tUsage:\n\t======\n\n\t\t# to go up 10 levels in your directory\n\t\tmcd 10\n\n\t\t# to go up just 2 levels\n\t\tmcd 2\n" >&2
        return 1;
    fi  

    up=""

    for ((i=1; i<=$1;i++)); do
        up="${up}../"
    done

    cd $up
}
| improve this answer | |
0

Do you know about autojump? It's a third party hack, but can be useful in your scenario.

| improve this answer | |
0

Try the rarely used environment parameter CDPATH. Then you might not have to explicitly set the level.

Example:

$ find workspace -type d
workspace
workspace/project1
workspace/project1/com
workspace/project1/com/java
workspace/project1/com/java/lang

$ CDPATH=".:~/workspace:~/workspace/project1:~/workspace/project1/com:~/workspace/project1/com/java:~/workspace/project1/com/java/lang"
$ cd com
$ pwd
~/workspace/project1/com

If working on multiple projects, you can make the CDPATH setting into a project specific environment file. And trigger it with a shim for additional automation.

I tend to use pushd and popd quite a lot. I tend to use CDPATH to let me hop between project trees rather than subdirs in a project - but at the moment I'm working on a lot of small projects, not a few big projects. :)

| improve this answer | |
0

If you are previously on the target directory:

luna:/tmp % mkdir -p a/b/c/d
luna:/tmp % pwd
/tmp
luna:/tmp % cd a/b/c/d
luna:d % pwd
/tmp/a/b/c/d
luna:d % cd -
luna:/tmp % pwd
/tmp
luna:/tmp % 
| improve this answer | |
0

Take a look at DirB. It's a BASH script that allows you to create bookmarks as follows:

OPERATIONS

  • s Save a directory bookmark
  • g go to a bookmark or named directory
  • p push a bookmark/directory onto the dir stack
  • r remove saved bookmark
  • d display bookmarked directory path
  • sl print the list of directory bookmarks

Very simple, very effective.

| improve this answer | |
0

Step further from @Grigory's answer:

function cd_up() {
if [ -z "$1" ]; then
    cd ..
else
    cd $(printf "%0.s../" $(seq 1 $1 ))
fi
}
alias 'cdd'='cd_up'

That is :

// go up 1 directory level 
$cdd

// go up 3 directory level 
$cdd 3
| improve this answer | |
0

Got sick of this exact same problem and ended up writing cd-plus as a result. A single file CLI utility that lets you cd up multiple directories.

Usage

echo `pwd` # /foo/bar/foobar/baz/foobaz/bazfoo
d baz

echo `pwd` # /foo/bar/
| improve this answer | |
0

Adding the below code to your .bashrc will extend cd's completion to honor three plus dot notation

_cd_dot_expansion() {
    local path="${COMP_WORDS[COMP_CWORD]}"

    if [[ "${path}" =~ ^\.{3,} ]]; then
        local dots="${BASH_REMATCH}"
        local levels="${#dots}"
        local tail="${path##*...}"
        local expanded_dots='..'

        # the loop starts at two because the first set of dots is
        # assigned to `expanded_dots` when it is initialized
        for (( i = 2; i < "${levels}"; i++ )); do
            expanded_dots+='/..'
        done

        path="${expanded_dots}${tail}"
        COMPREPLY=( $( compgen -A file "${path}" ) )

        return
    fi

    _cd
}

complete -o nospace -F _cd_dot_expansion cd

Once this snippet is run in your bash shell typing cd .../ and hitting <TAB> will complete the path to ../../ and list the relative paths of all of the directories that are two levels up, for instance.

Update: bash-completion must be installed to have access to the _cd method referenced in the code above. It's installable via most command line package managers

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.