1

How could I use something similar to cd -, which goes to the previous directory in history, in order to go back even further in directory history? For instance lets say my history is: (1 being current.)

  1. ~/
  2. ~/otherDirectory
  3. ~/really/long/directory/name/that/i/don't/want/to/type/again/but/dont/use/enough/to/make/an/alias/for

Using cd - here would bring me to ~/otherDirectory#2, and if i use it again it brings me back to ~/#1(which I don't want to be in) rather than to the really long directory #3(which I do want to be in). In summary how do I navigate further back into directory history? Is there some bash I could write to add this functionality?

I am trying to go back through directory history, (more than just one directory) much like one would go through command history using the up arrow. Hopefully this clarifies that this question has not been asked before.

muru
  • 197,895
  • 55
  • 485
  • 740

2 Answers2

3

Directory Stack in Bash

There is something know as directory stack or DIRSTACK in bash. Stack is a basic data structure in computer science, where you can store elements on top of each other(like a book stack), but access only most recent one (top).

Here's a small demo - each time i push something on to directory stack, my current working directory is set to that item; every time i pop - we delete the top (left-most ) item from stack, and return to next available item:

$>  # pushd navigates to and stores the directory given
$> pwd
/home/xieerqi
$> pushd bin
~/bin ~
$> pushd /etc
/etc ~/bin ~
$> # popd deletes leftmost item, returns to next directory on left$> pwd
/etc
$> popd
~/bin ~
$> pwd
/home/xieerqi/bin
$> 

The most recent item is always stored as the top of the stack, even when you use cd

$> dirs
/ /etc ~
$> cd /var
$> dirs
/var /etc ~
$> 

The dirs command allows us to retrieve an nth element from the stack. Using that output as argument to cd we can navigate to any directory that is on the stack, without affecting the stack itself. Notice bellow how /etc/ and ~ (stack elements 1 and 2) stay the same, even though I change my current working directory (and the top element as well)

$> dirs
/var /etc ~
$> dirs +1
/etc
$> cd $(dirs +1)
$> pwd
/etc
$> dirs
/etc /etc ~

Using DIRSTACK behavior to simulate web browser behavior

You know how in a web browser if you jump from url A to url B and url C, you can kind of go back and forth between them using back and front arrow keys ?

Well, we can do the same in bash with these two functions:

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

cdback()
{
  popd > /dev/null
  printf "Returned to:%s\n" "$( dirs +0)"

}

Functions have precedence over aliases, thus we can use that to our advantage , and make each cd call pushd on every argument it is given (and if none is given, we go back to home directory , same behavior, but it's recorded)

$> pwd
/home/xieerqi
$> cd /etc
$> cd /var
$> cd /usr
$> pwd
/usr
$> cdback
Returned to:/var
$> pwd
/var
$> cd
$> pwd
/home/xieerqi

Directory stack in other shells

csh has its own directory stack implementation, but ksh does not. You could use Eddie's implementation

Going up with a for loop

As for going a certain number of dirs up, you could write a function that calls cd .. certain number of times. For instance, here's my custom function in .bashrc

function goUp # go up x number of dirs
{
  num=$1
  while [ num -ne 0  ];do
    cd ..
    num=$( expr $num - 1   )
  done
}
# ---

So I would call this as goUp 3 to go up 3 directories, and it would call cd .. 3 times

Using inode number This method is good when This trick is often used when the folder name has difficult character/unrecognizable character. We find the inode number of the directory you want to go to using stat and then use combination of find and cd

$> stat $HOME/bin/sh/
  File: ‘/home/xieerqi/bin/sh/’
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 801h/2049d  Inode: 5795531     Links: 2
Access: (0775/drwxrwxr-x)  Uid: ( 1000/ xieerqi)   Gid: ( 1000/ xieerqi)
Access: 2015-08-19 15:27:38.280529273 -0600
Modify: 2016-02-20 17:03:49.822700405 -0700
Change: 2016-02-20 17:03:49.822700405 -0700
 Birth: -
$> cd $(find $HOME -inum 5795531 -type d 2>/dev/null)
$> pwd
/home/xieerqi/bin/sh

Of course this might be a bit slow, because find traverses the whole directory tree recursively.

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
0

If you're cd'd into ~/really/long/directory/name, and you want to be in just ~/really/long, you can use cd ~/really/long even if you're in a subdirectory of 'long'

If you've just left ~/really/long and you want to get back there, you can just do

Cd

And then use the up arrow to to through your command history to where you used

Cd ~/really/long