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:
pushd
- toggle the two directories from the top.pushd +1
- change to the second from top directory.pushd -0
- change to the bottom from top directory.popd +0
- pop the top changing to the second from top directory.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?
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.
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.
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.
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.
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.
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:
<ctrl>-^
- vim
hot key to toggle the current with the previous buffer.<alt>-<
- Shift left and carry.<alt>-x<
- Shift left and crop.<alt>->
- shift right and carry.<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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With