Introduction
Navigating the Linux filesystem is commonly accomplished using the cd command, which can often get inefficient. Several commands and options can be used for faster, more efficient directory navigation. This guide will introduce:
- pushd, popd, dirs (bash built-ins)
- autocd, cdable_vars, cdspell, dirspell (bash options)
- The bd utility.
A Debian 10 system will be used for demonstration.
Prerequisites
A Linux system with bash is required.
pushd/popd
Bash can use a stack to store directory paths, which allows you to change into previous directories, similarly to the “back” button in graphical file managers. pushd PATH
pushes ‘PATH’ onto the stack, displays the paths stored in the stack, and changes the working directory to ‘PATH’. On the other hand, popd
pops (removes) the last directory from the stack, displays the stack content, and changes to that directory. For example:
root@debian:~# pushd /etc/ssh
/etc/ssh ~
root@debian:/etc/ssh# pushd /home
/home /etc/ssh ~
root@debian:/home# pushd /etc/X11/xkb/
/etc/X11/xkb /home /etc/ssh ~
root@debian:/etc/X11/xkb# popd
/home /etc/ssh ~
root@debian:/home# popd
/etc/ssh ~
root@debian:/etc/ssh# popd
~
root@debian:~#
For convenience, you can replace cd
with a helper function that uses the cd
builtin to change directories while using pushd
to push the new directory onto the stack, allowing you to use the cd
command as your normally would, and popd
to go back.
cd() {
if [ $# -eq 0 ]
then
builtin cd $HOME && pushd -n $OLDPWD 1>/dev/null
else
builtin cd "$*" && pushd -n $OLDPWD 1>/dev/null
fi
}
You can install the above function as follows:
cat <<EOF >> ~/.bashrc
cd() {
if [ \$# -eq 0 ]
then
builtin cd \$HOME && pushd -n \$OLDPWD 1>/dev/null
else
builtin cd "\$*" && pushd -n \$OLDPWD 1>/dev/null
fi
}
EOF
. ~/.bashrc
dirs
When executed without any arguments, dirs
displays the stack contents on a single line:
root@debian:/etc/X11/xkb# dirs
/etc/X11/xkb /home /etc/ssh ~
Use the -v
flag for a format that is easier to read. (Numbering starts at 0 with the last directory) :
root@debian:/etc/X11/xkb# dirs -v
0 /etc/X11/xkb
1 /home
2 /etc/ssh
3 ~
Use the -c
flag to clear the stack:
root@debian:/etc/X11/xkb# dirs #directory stack contains 4 entries
/etc/X11/xkb /home /etc/ssh ~
root@debian:/etc/X11/xkb# dirs -c #clears directory stack
root@debian:/etc/X11/xkb# dirs #directory stack contains a single entry (the current working directory)
/etc/X11/xkb
Bash options
Bash provides numerous optional features, several of which can make navigating the filesystem easier and more efficient. These options can be set and unset with shopt -s
and shopt -u
respectively, as shown below:
shopt -s opt1 opt2 opt3 ... # enabling bash options
shopt -u opt1 opt2 opt3 ... # disabling bash options
A list of the current enabled options is stored in the $BASHOPTS variable:
root@debian:~# echo $BASHOPTS
checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:interactive_comments:login_shell:progcomp:promptvars:sourcepath
The full list of bash options and their state (on/off) can be viewed by running shopt
.
Changes made using shopt do not persist beyond the current shell session. To permanently enable/disable a bash option, add the corresponding shopt command to your .bashrc.
autocd
With this option, typing the name of a directory as if it were a command, changes to that directory, for example:
root@debian:~# shopt -s autocd
root@debian:~# /etc
cd -- /etc
root@debian:/etc#
cdable_vars
The cdable_vars bash option allows passing a variable name without the ‘$’ character, that contains a directory path, to cd. If the argument to cd is not a directory, it is assumed to be a variable name.
root@debian:~# shopt -s cdable_vars
root@debian:~# src=/root/Documents/myprojects/project1/src/
root@debian:~# cd src
/root/Documents/myprojects/project1/src/
root@debian:~/Documents/myprojects/project1/src#
cdspell
With this option, bash tries to (non-interactively) correct minor spelling errors in a directory path supplied to cd. :
root@debian:/etc# shopt -s cdspell
root@debian:/# cd /et/sh
/etc/ssh
root@debian:/etc/ssh# cd /hmoe
/home
root@debian:/home# cd /usrr
/usr
root@debian:/usr#
The only errors corrected are a single missing character, a single extra character, and transposed characters. Bash does not attempt to correct any other error:
root@debian:~# cd /vaarr
-bash: cd: /vaarr: No such file or directory
dirspell and direxpand
This option enables spelling corrections of directory names during TAB completion (i.e. after pressing :key_tab:). In order for dirspell to work, the direxpand option must be enabled as well. To demonstrate:
shopt -s dirspell direxpand
ls /vra/lib
then press TAB, the line is replaced with ls /var/lib/
.
bd
bd is a third party script that allows you to quickly change to one of the parent directories of the current working directory. For instance, if the current working directory is ~/Documents/myprojects/project1/src/lib
, and you want to change to the myprojects
directory, you would use either cd ~/Documents/myprojects
or cd ../../..
. With bd, the same directory change can be done by running bd m
.
Installation
- Debian/Ubuntu: bd is available in the official repositories and can be installed using
apt install -y bd
. - Other Distributions: Download the bash script from Github and set the readable and executable permissions:
wget -O /usr/local/bin/bd https://raw.github.com/vigneshwaranr/bd/master/bd
chmod +rx /usr/local/bin/bd
Next, create an alias in .bashrc
that runs bd in the current shell with the -si
option, which enables partial name matching.
echo 'alias bd=". bd -si"' >> ~/.bashrc
. ~/.bashrc
Using bd
With the alias shown above, bd supports partial name matching and is case-insensitive. The following three commands perform the same directory change:
root@debian:~/Documents/myprojects/project1/src/lib# bd Documents
/root/Documents/
root@debian:~/Documents/myprojects/project1/src/lib# bd doc
/root/Documents/
root@debian:~/Documents/myprojects/project1/src/lib# bd d
/root/Documents/
root@debian:~/Documents#
If more than one parent directory matches the starting characters supplied to bd, the closest (to your CWD) directory is matched. For instance:
root@debian:~/Documents/mydocs/myprojects/project1/src/lib# bd my
/root/Documents/mydocs/myprojects/
root@debian:~/Documents/mydocs/myprojects#
References
- BASH(1) Manual
- BASH-BUILTINS(7) Manual
- bd(1) Manual
- https://github.com/vigneshwaranr/bd