Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to leverage the clumsy pushd and popd with the awsome dirs built-in command of Bash

Isn't there a more intuitive way of dealing with the directory stack than what is possible with pushd and popd?

I find the CLIs of the pushd and popd built-in commands presented to the user kind of mind-boggling. But at the same time I would love to make frequent use of the directory stack presented by the dirs built-in command.

So it took me quite a long time to figure out use cases and then to memorize the following ones:

  1. pushd - toggle the two directories from the top.
  2. pushd +1 - change to the second from top directory.
  3. pushd -0 - change to the bottom from top directory.
  4. popd +0 - pop the top changing to the second from top directory.
  5. pushd -0; popd +1 - change to the bottom from top directory and pop the former top.

Still having to type them each time just to juggle with the directory stack feels way to heavy to me. I even can't come up with mnemonic names to alias those five use cases.

Any insights?

like image 790
Tim Friske Avatar asked Nov 15 '12 16:11

Tim Friske


People also ask

How do you use pushd and popd?

pushd and popd allow you to manipulate the directories on stack. When you pushd a directory, you put the current directory on the stack and change directory to the one specified as a parameter. popd will allow you to go back to the directory on the stack.

What happens when you use the pushd command?

The pushd command is used to save the current directory into a stack and move to a new directory. Furthermore, popd can be used to return back to the previous directory that is on top of the stack. It is very useful when we have to switch between two directories frequently.

How do you use popd command?

popd command is used to remove directories from the directory stack. The “d” in popd stands for the directory as it removes the directory path onto the stack. After this command is executed, the present directory stack is displayed as a list of space-separated directories.

What is pushd command in CMD?

Stores the current directory for use by the popd command, and then changes to the specified directory. Every time you use the pushd command, a single directory is stored for your use. However, you can store multiple directories by using the pushd command multiple times.


2 Answers

For my own personal use, I have several directories that I commonly use, and would like to be able to switch between using pushd. I came up with the following function for my .bashrc:

p() {
  pushd +"$(($(dirs -p | sed -n '1d;s,.*/,,;/^'"$1"'/{=;q;}')-1))" >/dev/null
}

Let's say I have a directory stack like so:

$ dirs -v
 0  ~/repos/local_only/configs
 1  ~/repos/virtualization
 2  ~/repos/local_only/work
 3  ~/repos/core
 4  ~/repos/local_only/my_test_repo

I can switch from the current directory to any other using just p <letter>, where <letter> is the start of the name of the directory. (It can be more than one letter, of course.) For instance, p m will switch to my_test_repo; p w will switch to work.

If I use p c from my work dir, it will switch to the next directory in the stack which starts with c, which in this case would be core. (The q part of the sed command prevents it from returning more than the first result.) To specifically switch to the configs dir instead, I could use p con, or just p c and then p c again.

The 1d in the sed command is so that I don't ever switch to the current directory. Thus I can switch between my configs dir and my core dir using just p c.

The redirection of stdout to /dev/null prevents the annoying (to me) execution of dirs after every execution of pushd. (I have the current directory listed in my prompt anyway.) However I don't silence stderr—so if I run p q, for example, I'll see:

$ p q
-bash: pushd: +-1: directory stack index out of range

Complementary with builtins

This doesn't replace pushd and popd; it's intended for fast switching. To add to the directory stack I still use pushd <directory_name>. And if I'm done in a specific directory (say, virtualization) I can just p v and then popd.


Unlikely Errors:

This probably won't work right with directory names that contain newlines, but that doesn't matter for my purposes. In any case the worst it could do is pushd you to the wrong directory.

like image 24
Wildcard Avatar answered Oct 19 '22 12:10

Wildcard


Recently I discovered the power of GNUs readline library and the short cuts in terms of key strokes it can provide to the user on Bash's command line.

I therefore defined the following hot keys in my ~/.inputrc file. GNU readline's configuration file:

# "pushd" use case.
"\C-^": "\C-a\C-kpushd\C-m"

# "pushd +1" use case.
"\e<": "\C-a\C-kpushd +1\C-m"

# "popd +0" use case.
"\ex\e<": "\C-a\C-kpopd +0\C-m"

# "pushd -0" use case.
"\e>": "\C-a\C-kpushd -0\C-m"

# "pushd -0; popd +1" use case.
"\ex\e>": "\C-a\C-kpushd -0; popd +1\C-m"

I associate the hot keys from above as follows:

  1. <ctrl>-^ - vim hot key to toggle the current with the previous buffer.
  2. <alt>-< - Shift left and carry.
  3. <alt>-x< - Shift left and crop.
  4. <alt>-> - shift right and carry.
  5. <alt>-x> - shift right and crop.

The <ctrl>-ak key strokes position the cursor at the beginning of the line (a) and delete (k) it. This is important because when <ctrl-m> (enter) is hit chances are that the user hit the hot key while in the middle of a sentence. The hot key value would get garbled with the current user input and bash couldn't execute it.

like image 76
Tim Friske Avatar answered Oct 19 '22 11:10

Tim Friske