Do you sometimes forget the actual location of directories & have to juggle through cd
& ls
to know the right path?
In this short post, we discuss how to make a "smart" alternative to cd
command on Linux (& probably MacOS 🙄).
The problem is simple we just need to automate this task of finding the actual location of directories and the 2 most popular commands to do that are find
& locate
:
1. locate
- Used to search for files, much faster than
find
. - Limited functionality.
- Depends on external database for fast finding (
/var/lib/mlocate/mlocate.db
).
# search file paths which exactly match the pattern, "memes"
locate -r '/memes$' | grep $HOME
2. find
- Extensive options.
- Can search for both files & directories.
- Slower than
locate
.
# search for directory "memes" inside your home dir.
find -O2 $HOME -name "memes" -type d
Ok then basics clear, now we write a small bash
function to create scd
(smart cd
).
scd() {
if [[ $1 != "" ]]; then
while read -r value; do
if [[ -d $value ]]; then
printf "%s\n" "Hit 🎯: $value"
cd "$value"
fi
done < <( locate -e -r "/$1$" | grep "$HOME" )
else
cd "$HOME" || return
fi
}
That's it, 12 liner (a little) better alternative to cd.
Now you can add it to your .bashrc
or better create a .bash_functions file and source it in your default shell config.
if [ -f ~/.bash_functions ]; then
. ~/.bash_functions
fi
Note: If you are on Mac,
locate
would probably be not available, usefind
instead.
Not yet convinced?
Ok, a more advance version with options like ..
, -
scd() {
if [[ $1 != "" ]]; then
case $1 in
[".."]* ) cd .. ;;
["-"]* ) cd - ;;
["/"]* ) cd / ;;
* ) while read -r value; do
if [[ -d $value ]]; then
printf "%s\n" "Hit 🎯: $value"
cd "$value"
fi
done < <( locate -e -r "/$1$" | grep "$HOME" ) ;;
esac
else
cd "$HOME" || return
fi
}
Cons 😤
-
Well, one of the problems with our bash function is that we wouldn't be able to leverage "tab" auto-suggestions.. Read More - Newly created directories won't be readily available with the
locate
command as it depends on its own databasemlocate.db
. The database is updated automatically by our system through a cron job. Although you can still do it manually.
sudo updatedb
Pros 📈
- Don't have to search for directory paths & cd into it.
- Even if
scd
switches to the wrong directory (in case of multiple matches), you will still be able to see what's the actual path in output & then switch to it manually.
what do you think?
UPDATE: 9 Aug 2020
The CDPATH
Thanks to Santosh's comment on my LinkedIn post there is another way of switching directories "smartly".
CDPATH
can be used as a search path for the cd command. A colon-separated list of directories in which the shell looks for destination directories specified by the cd command.
It gives you a limited functionality to cd into sub-directories of a specific parent directory.
For e.g in your .bashrc
or .zshrc
add this line.
export CDPATH=".:/home/bhupesh/Desktop"
And now you can freely switch directories inside Desktop & would not have to use cd ~/Desktop/dirB
or cd /home/username/Desktop/dirB
.
Well of-course now you need to do this manually & find out which directories you usually spent more time in.
UPDATE: 17 Aug 2020
Tab Auto-suggestions
Thanks to Thamara's comment, I recently added "tab" suggestions powered by bash_completions.
How to use ?
- Start a new bash session.
- Source the completions script
source scd-completions.bash
. Get it from here. -
Create a new version of
scd
function :
scd() { if [ -z "$1" ]; then echo "No directory path provided" exit 2 else echo "$1" cd "$1" || return fi }
-
Create a
.inputrc
file in your HOME directory with following options enabled. Read More about these options.
set show-all-if-ambiguous on set completion-ignore-case on set completion-map-case on set show-all-if-unmodified on set menu-complete-display-prefix on "\t": menu-complete%
scd
<search-string>[TAB][TAB]
Pressing [TAB] one time triggers the completion. Pressing it twice will automatically complete the command.
Top comments (12)
Install
z
- it's awesome - github.com/rupa/zDid you mean the Z Shell ?. It actually is great but it's limited compared to features available in bash
Nope - check out the GitHub link
I want to hear about these bash features that zsh doesn't have.
mapfile
/readarray
for example is a very handy thing in bash which is not in zshAnother one which I like
read -p "Enter Password"
doesn't work in zshThanks for this Bhupesh. My team lead at my previous job introduced me to Bash aliases. I created a few aliases to help me with navigating to files and directories that I used every day. I'd never thought to go beyond that, but after seeing your post I may have to tinker with it. Thanks again!
Thanks a lot (you are probably the first reader 🙈), glad it helped 🔥
I am still amazed by how much we can customize our shell
That's pretty neat !
The only thing is.... why
cd "$1" || exit
? If for some reason there's, say, a permission issue on that folder, or a broken symlink,exit
will actually terminate your current shell session... surely not the effect you want from a function? Likely this should bereturn
Yes, I absolutely agree (the thing is I it realized sometime later after I first published the blog)
I have updated it now
thanks for pointing it out 👍
You have opened up a new array of ideas with this post. Thanks. Keep it up bro! 😊
🤟🏼 thanks
Thanks for this!