Bookmarking directories When working on a large codebase, I often need to switch between deeply nested directories quickly. To make my life easier, I came up with a bookmarking script.

#!/bin/bash

bm_list() {
    for i in "${!BOOKMARKS[@]}"; do
        echo -e $i'\t'"${BOOKMARKS[$i]}" ;
    done
}

bm_go() {
    cd "${BOOKMARKS[$1]}"
}

bm_add() {
    for i in "${!BOOKMARKS[@]}"; do
        [[ "$1" == ${BOOKMARKS[$i]} ]] &amp;&amp; return
    done
    BOOKMARKS+=("$1")
}

bm_clear() {
    unset BOOKMARKS
}

bm_delete() {
    unset BOOKMARKS[$1]
}

bm_compact()
{
    local SIFS="$IFS"; IFS=
    BOOKMARKS=("${BOOKMARKS[@]}")
    IFS="$SIFS"
}

bm_load() {
    local bmfile=${1:-~/.bookmarks}
    local SIFS="$IFS"; IFS=$'\n'
    bm_clear
    while read -d ''; do BOOKMARKS+=("$REPLY"); done &lt; "$bmfile"
    IFS="$SIFS"
}

bm_save() {
    local bmfile=${1:-~/.bookmarks}
    printf '%s\0' "${BOOKMARKS[@]}" &gt; "$bmfile"
}

bm_help() {
    cat &lt;&lt;-EOF
bm: bookmark directories
Usage:
    bm                   bookmark current directory
    bm -l
    bm list              list bookmarks
    bm index
    bm -g index
    bm go index          cd to bookmark at index
    bm -d index
    bm delete index      delete bookmark at index
    bm -s [filename]
    bm save [filename]   save bookmarks in the file (default ~/.bookmarks)
    bm -L [filename]
    bm load [filename]   load bookmarks from the file (default !/.bookmarks)
    bm -c
    bm clear             remove all bookmarks
    bm -C
    bm compact           compact indices to a sequential list
EOF
}

bm() {
    local command=$1; shift
    case $command in
        -l | list ) bm_list ;;
        -g | go ) bm_go "$1" ;;
        -d | delete ) bm_delete "$1";;
        -s | save ) bm_save "$1" ;;
        -c | clear ) bm_clear ;;
        -C | compact ) bm_compact ;;
        -L | load ) bm_load "$1" ;;
        '') bm_add "$PWD" ;;
        *) [[ "$command" =~ [0-9]+ ]] &amp;&amp; bm_go "$command" || bm_help ;;
    esac
}
Some suggestions:


#!/usr/bin/env bash is a very common shebang line these days.
Use More Quotes™:


echo -e $i'\t'"${BOOKMARKS[$i]}" should be echo -e $i'\t'"${BOOKMARKS[$i]}" (or even better, printf '%s\t%s' "$i" "${BOOKMARKS[$i]}")
command=$1 should be command="$1"

In [[ "$command" =~ [0-9]+ ]] you'll want to anchor the regex.
If this is for your own use I don't quite understand the need for both option-style and command-style invocation.
== in Bash is a bit of a historical accident. It won't make any difference as long as you use Bash, but I usually prefer the POSIX = in this case.
It seems bm_compact should run on every change, since it'll be super fast and you avoid changing indexes.
bmfile would be better as either configuration or as a single variable.
"default !/.bookmarks" should probably be "default ~/.bookmarks".
You can set IFS for a single command, such as while IFS=… read …
All the single semicolons are extraneous - you definitely don't need one for echo -e $i'\t'"${BOOKMARKS[$i]}" ;, and you can use

for i in "${!BOOKMARKS[@]}"
do


for loops and conditionals.