DEV Community

loading...
Cover image for Creating a smart alternative to 'cd' command

Creating a smart alternative to 'cd' command

bhupesh profile image Bhupesh Varshney ๐Ÿ‘พ Originally published at bhupesh.codes ใƒปUpdated on ใƒป3 min read

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
}

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Note: If you are on Mac, locate would probably be not available, use find 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
}
Enter fullscreen mode Exit fullscreen mode

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 database mlocate.db. The database is updated automatically by our system through a cron job. Although you can still do it manually.
sudo updatedb
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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.

scd demo gif

How to use ?

  1. Start a new bash session.
  2. Source the completions script source scd-completions.bash. Get it from here.
  3. 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
    }
    
  4. 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% 
    
  5. scd <search-string>[TAB][TAB]

Pressing [TAB] one time triggers the completion. Pressing it twice will automatically complete the command.

Discussion (12)

pic
Editor guide
Collapse
jonrandy profile image
Collapse
bhupesh profile image
Bhupesh Varshney ๐Ÿ‘พ Author

Did you mean the Z Shell ?. It actually is great but it's limited compared to features available in bash

Collapse
jonrandy profile image
Jon Randy

Nope - check out the GitHub link

Collapse
vonheikemen profile image
Heiker

I want to hear about these bash features that zsh doesn't have.

Thread Thread
bhupesh profile image
Bhupesh Varshney ๐Ÿ‘พ Author • Edited

mapfile/readarray for example is a very handy thing in bash which is not in zsh
Another one which I like read -p "Enter Password" doesn't work in zsh

Collapse
jasonf profile image
Jason F

Thanks 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!

Collapse
bhupesh profile image
Bhupesh Varshney ๐Ÿ‘พ Author

Thanks a lot (you are probably the first reader ๐Ÿ™ˆ), glad it helped ๐Ÿ”ฅ
I am still amazed by how much we can customize our shell

Collapse
taikedz profile image
Tai Kedzierski

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 be return

Collapse
bhupesh profile image
Bhupesh Varshney ๐Ÿ‘พ Author

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 ๐Ÿ‘

Collapse
idrisrampurawala profile image
Idris Rampurawala

You have opened up a new array of ideas with this post. Thanks. Keep it up bro! ๐Ÿ˜Š

Collapse
bhupesh profile image
Bhupesh Varshney ๐Ÿ‘พ Author

๐ŸคŸ๐Ÿผ thanks

Collapse
delta456 profile image
Swastik Baranwal

Thanks for this!