4

I know IDEs are the wave of the future, but I always find myself coding in vim in a Linux terminal. Old dog. New tricks.

Anyway, navigation becomes challenging when dealing with long package names. For instance, in my terminals I can see my current path as part of the prompt. Sometimes I am here:

/foo/bar/src/com/example/yomama/

and I want to get to:

/foo/bar

I have some nifty aliases:

alias 1down="cd .."
alias 2down="cd ..;cd .."
alias 3down="cd ..;cd ..;cd .."
alias 4down="cd ..;cd ..;cd ..;cd .."
alias 5down="cd ..;cd ..;cd ..;cd ..;cd .."

So if I type 4down, bam! I am at /foo/bar.

The thought just occurred to me that since I know my current working directory is:

/foo/bar/src/com/example/yomama/

I can also just go 2 up from / to get to /foo/bar.

So it would be cool to also implement a 2up function, since it is easier to count how many to go up. Before I start to write out a shell script for this, I am wondering if there are any shell tools that would lend a more elegant solution. Extra points if someone knows of one-liner that can implement Nup.

PS: I already have

alias bar = "cd /foo/bar"

I am looking for a more generic solution here.

PPS: I have always thought that it would be really cool to have a clickable $PWD in the prompt. So I could just click on bar, and cd to /foo/bar. But maybe I should just move to a graphical IDE and shut up already ;-)

EDIT:

There is some confusion on what my definition of Nup is.

Nup should take you to the Nth path location in your PWD from root. So, if you are currently in /a/b/c/d/e/f/g/h/i, 4up will take you to /a/b/c/d. Similarly 5down will get you /a/b/c/d.

Basically, you can navigate the path without having to laboriously 'cd ..' a bunch of times, or specifying 'cd /a/b/c/d'.

7
  • These might be of relevance to you superuser.com/questions/299694/… Commented Aug 23, 2013 at 16:03
  • I too avoid IDEs as much as possible! But they do have such nice features. If you use vim you need to checkout the Command T plugin which is great for java projects because it allows you to sloppy search for a file underneath the current dir to open it which is great for java with its nested folders. You also should consider using pushd/popd for dir navigation. eriwen.com/bash/pushd-and-popd Good luck!
    – jmathew
    Commented Aug 23, 2013 at 16:04
  • Take a look at the vim plugin nerdtree: vim.org/scripts/script.php?script_id=1658. Video of it in action here: net.tutsplus.com/tutorials/other/vim-essential-plugin-nerdtree
    – slm
    Commented Aug 23, 2013 at 16:30
  • You wont be able to click it, but using GNU Screen you could setup several tabs to move through various folders. Example: window 1 is /tmp/foo, window 2 is /tmp/foo/bar, etc.
    – Tim
    Commented Aug 23, 2013 at 16:39
  • You do know you can navigate directories via a clickable list in vim? Try vim ., or in command mode :e [some directory path]. The thing about IDE's is you won't find one with the editing features of vim. I sometimes run eclipse and gvim side-by-side, but I do the editing in gvim and then let eclipse reload the file for whatever feature I need from there. Throw in the vim TListToggle plugin and configure set complete right and you are most of the way to an IDE anyway.
    – goldilocks
    Commented Aug 23, 2013 at 16:49

4 Answers 4

2

With two functions in your .bashrc file, you can use the directory stack for some navigation

function down ()
{
  if [[ -z "$1" ]]
  then
   n=1
  else
   n=$1
  fi

  for ((i=0; i<$n; i++ ));
  do
      pushd .. > /dev/null
  done;
}
function up ()
{
  if [[ -z "$1" ]]
  then
   n=1
  else
   n=$1
  fi

  for ((i=0; i<$n; i++ ));
  do
      popd > /dev/null
  done;
#  dirs -c  # To clear directory on up motion
}

Where you can use down N and up N, respectively.

Sample usage:

~/tmp/bash/dir1/dir2/dir3$ down 4
~/tmp$ up 2
~/tmp/bash/dir1$ up 2
~/tmp/bash/dir1/dir2/dir3$ down 2
~/tmp/bash/dir1$ down 1
~/tmp/bash$ up 3
~/tmp/bash/dir1/dir2/dir3$

Of course, you cannot use up N before using down N. Unexpected things might happen, or error messages may appear.

3
  • I think there is miscommunication on what upN should do. up2 should not take me 2 up from where I was, but instead take me 2up in my pwd. So if I am in /a/b/c/d/e/f, 2up should put me in /a/b.
    – rouble
    Commented Aug 28, 2013 at 16:55
  • @prmetta Then down and up are both going down (or up)? That is a bit of weird definition.
    – Bernhard
    Commented Aug 28, 2013 at 21:17
  • I tend to agree. The choice of words may not be the best. But the usecase is valid and very common. I usually find myself in a long path such as /a/b/c/d/e/f/g/h/i/j. Sometimes I may want to get to 'g' so going 3down makes sense to me. Other times I want to get to 'c', but I don't want to count how many to go down, so going 3up from '/' makes sense to me.
    – rouble
    Commented Aug 29, 2013 at 2:13
1

Here's my approach that allows you to move back and forth, and also return to any previous directory you've been in. This can be especially valuable when you find yourself navigating back and forth to different parts of your file system (fairly common during development).

Supports:

up # (go up any # of directories)
goback 
goback # (the # is optional to go back any #)
prev (go to the last dir you were in)

This also allows for you to cd into a directory anywhere on your system and then return to to the previous directory, as it saves the location of the last directories you were in.

Note: Scroll to the very bottom for a super condensed version of this.

Step 1: Edit (nano/vim) ~/.bashrc and add the following to the bottom:

declare -a DIR_STACK

cd() {
    DIR_STACK+=("$PWD")
    builtin cd "$@" && pwd || { unset 'DIR_STACK[-1]'; return 1; }
}

up() {
    local count=${1:-1}
    for _ in $(seq 1 $count); do
        [[ $PWD != / ]] && DIR_STACK+=("$PWD") && builtin cd .. || { echo "Error: Reached root directory."; return 1; }
    done
    pwd
}

goback() {
    local count=${1:-1}
    while [[ ${#DIR_STACK[@]} -gt 1 && count -gt 0 ]]; do
        builtin cd "${DIR_STACK[-2]}"
        unset 'DIR_STACK[-1]' && ((count--))
    done
    [[ $count -eq 0 ]] && pwd || echo "Error: Cannot go back any further."
}

prev() {
    [[ -n $OLDPWD ]] && builtin cd - > /dev/null && pwd || echo "Error: No previous directory stored."
}

Step 2. source ~/.bashrc

Step 3. Here's how it works:

[root@agent colors]# pwd
/etc/xdg/colors
[root@agent colors]# cd /
/
[root@agent /]# goback
/etc/xdg/colors
[root@agent colors]# cd ..
/etc/xdg
[root@agent xdg]# goback
/etc/xdg/colors
[root@agent colors]# cd ../../
/etc
[root@agent etc]# goback
/etc/xdg/colors
[root@agent colors]# up 2
/etc
[root@agent etc]# goback
/etc/xdg/colors
[root@agent colors]# cd ..
/etc/xdg
[root@agent xdg]# prev
/etc/xdg/colors
[root@agent colors]# cd /
/
[root@agent /]# goback 3
/etc/xdg/colors
[root@agent colors]# up 3
/
[root@agent /]# goback 3
/etc/xdg/colors

A condensed version (less readable) for your .bashrc:

declare -a DIR_STACK
cd() { DIR_STACK+=("$PWD"); builtin cd "$@" && pwd || { unset 'DIR_STACK[-1]'; return 1; }; }
up() { local count=${1:-1}; for _ in $(seq 1 $count); do [[ $PWD != / ]] && DIR_STACK+=("$PWD") && builtin cd .. || { echo "Error: Reached root directory."; return 1; }; done; pwd; }
goback() { local count=${1:-1}; while [[ ${#DIR_STACK[@]} -gt 1 && count -gt 0 ]]; do builtin cd "${DIR_STACK[-2]}"; unset 'DIR_STACK[-1]' && ((count--)); done; [[ $count -eq 0 ]] && pwd || echo "Error: Cannot go back any further."; }
prev() { [[ -n $OLDPWD ]] && builtin cd - > /dev/null && pwd || echo "Error: No previous directory stored."; }
0

This is not exactly the answer you asked for, but something you may be interested in is the midnight commander filebrowser, which should be available in any linux distro repository. mc uses curses like console vim; it provides a two panel file browsing interface with a command prompt at the bottom; you can navigate directories using the arrow keys and type commands (to navigate command history, use ctrl-n and ctrl-p). Ctrl-o toggles the interface up and down -- when it is up, you're in a normal subshell in the same directory. You can start vim from within it, and if you set EDITOR=vim in your environment and uncheck the "use internal edit" in Options->Configuration, pressing F4 with a file highlighted will vim it. It is well worth learning to use and counts as one of my fav pieces of software ever.

In an X terminal the interface can be used with the mouse; you can also use a mouse in a VT if you install gpm.

0

I appreciate all the comments and responses. I used my noodle this morning and came up with:

alias 1up='cd /$(echo $PWD | cut -f 2 -d /)'
alias 2up='cd /$(echo $PWD | cut -f 2,3 -d /)'
alias 3up='cd /$(echo $PWD | cut -f 2,3,4 -d /)'
alias 4up='cd /$(echo $PWD | cut -f 2,3,4,5 -d /)'
alias 5up='cd /$(echo $PWD | cut -f 2,3,4,5,6 -d /)'

Note that the single quotes are essential so that bash does not expand pwd in the alias. I could write a function for this, but 5up and 5down are all I need.

Comments appreciated. One desire I do have is to have used pure bash to parse out the path variables instead of using cut - but I have real work to do ;-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .