I just made this little cd function that is a drop-in replacement for the builtin bash cd command. The idea was to make it really easy and productive to navigate around to commonly used directories in bash without forcing someone to learn new habits like in the case of pushd, popd, and a bunch of other stuff like cdargs and gotodir.
cd ()
{
if [ "$*" = "" -o "$*" = "-" ]; then
builtin cd $*;
return;
fi;
realpath=$(realpath $*);
if [ -z "$realpath" -o ! -d "$realpath" ]; then
realpath=$(realpath ~/recent_dirs/$* 2> /dev/null);
fi;
if builtin cd $realpath; then
if [ "$*" = "" -o "$*" = "-" ]; then
return;
fi;
ln -s $realpath ~/recent_dirs 2>/dev/null;
else
:;
fi
}
Your solution is the nicest I’ve seen for the problem of directory bookmarks. However, I think the notion of history needs to be per-shell, not global across all shells. For directories, a $DIRSTACK-style working set is probably more useful than a strict browser-style history, so I extended your solution by adding:
# cd [dir|N|pattern] # # if arg is a directory, then # if arg has > 2 slashes, then # bookmark dir and pushd there # else # cd there # else if arg is a number N # cd to Nth entry of $DIRSTACK # else if arg is a substring in $DIRSTACK # cd to first matching entry # else if arg is a substring in bookmarks # cd to newest matching entry # else # attempt to cd to arg using $CDPATH cd () { if [ "$*" = "" -o "$*" = "-" ]; then builtin cd ${1+"$@"} return fi local target if [ -d "$*" ]; then slashes=${1//[^\/]} # deletes all non-slashes if [ ${#slashes} -gt 2 ]; then pushdir "$1" return fi fi # if the non-numeric part of $1 is empty... if [ -z "${1//[0-9]}" ]; then # ...then go to Nth DIRSTACK entry target=`builtin dirs -l +"$@" 2> /dev/null` fi if [ -z "$target" ]; then target=`builtin dirs -p -l | grep -i "$1" | head -1` fi if [ -z "$target" ]; then target=`dirz -t | grep -i "$1" | head -1` fi if [ -z "$target" ]; then target="$1" fi if builtin cd $target; then : else echo "Also no match in DIRSTACK or ~/dirs" > /dev/stderr fi } # pushdir dir - pushd dir after bookmarking via a symlink in ~/dirs pushdir () { local dest="$1" # if relative, prepend PWD if [ "${dest:0:1}" != "/" ]; then dest="${PWD}/${dest}" fi # ln confused by trailing slash, so delete dest=${dest%/} ln -sf "$dest" ~/dirs builtin pushd "$dest" > /dev/null } # dirz [-t] - list bookmarked dirs sorted [by time] dirz () { local ordercmd=sort if [ "$1" == "-t" ]; then ordercmd=cat; fi /bin/ls -lt ~/dirs | tail +2 | sed 's/.* -> //' | $ordercmd }Hmm, some kind of markup system is in effect here, but WordPress doesn’t offer preview or convenient compose help. Marc can see the code in ~holtz/.bash_function; others may be out of luck. 🙂
I did a little bit of cleanup in your comment to get around some of the automatic WordPress formatting, but I think it’s still getting a bit screwed up. Maybe I can just upload a copy as a plain text file to my site.
Nice… how about some directions on using it? For example, when I try to cd into a dir now, I get “bash: realpath: command not found” — are there dependencies you might want to tell the rest of us how to fulfill?
Thanks!
-jq