Neither one nor Many

March 23 2013

The New KornShell

I prefer ksh (Version JM 93u+ 2012-02-29) for my shell (with "set -o vi"). Not that it's soooo much better than bash as a cli (and it's probably pwnd by some of zsh's features like programmable autocomplete). But I do find it alot cleaner than bash for scripting. Anyway, currently I've given all machines I work with a /bin/ksh and chsh'd it for my user, but I noticed I missed bookmarking the current directory with "pushd ." for returning to it later with "popd" (after i.e. some subtask that will make you endup /nowhere/near/your/old/far/away/path).

Sometimes you just don't want to open a new tab in screen. (And you are right, you could of course also use goto.cpp for bookmarking img1) An alternative solution would be starting- and exiting a subshell.

Found: dirstack.ksh by Eddie

So I googled and found this stack overflow answer which has a pretty nice pushd/popd/dirs implementation. But it behaves a little different: "pushd /usr" bookmarks and changes to that directory (the normal behaviour). But what I often want is to store a directory right before I'm about to leave it. (Chances are I didn't use "pushd" but "cd" to get there in the first place.) Normally you simply use "pushd ." to put it on the stack (and ignore the useless changedir on the side img1). But this implementation is explicitly designed so that the current directory is already (and always) the first (or zeroth position) on the stack and from that line of thought it would be "useless" to put it as a "duplicate" in the list.

I still want to use pushd on $PWD, so I commented these four lines in dirstack.ksh:

     # check for duplicate stack entries
     # current "top of stack" = ids; compare ids+dsdel to $PWD
     # either "ids" or "dsdel" must increment with each loop
     (( ids = 1 ))          # loop from bottom of stack up
     (( dsdel = 0 ))        # no deleted entries yet
     while [ ids+dsdel -le sd ] ; do
>>>>    #if [ "${dir_stack[ids+dsdel]}" = "$PWD" ] ; then
>>>>    #   (( dsdel = dsdel + 1 ))  # logically remove duplicate
>>>>    #else
           if [ dsdel -gt 0 ] ; then        # copy down
           (( ids = ids + 1 ))
>>>>    #fi

Then I remembered my book (that has caused me many jealous colleagues :+) also provided pushd and popd as examples in the appendix img1.

So I was curious to see if these were usable (the book is from 1995).

Found: fun/{pushd|popd|dirs} by David G. Korn himself*

* by my guess

SuSE provides these scripts in /usr/share/ksh/fun so I didn't need to type them in. If you need them, I tarballed them into kshfun.tar.gz (md5=7173831211d3d54f26f630f3cc720282). I was surprised by /usr/share/ksh/fun/dirs, they re-alias "cd" with a custom "_cd" function that does basically "pushd" all the time, with a stack of max. 32 dirs. That's a cool idea, you can view your stack with "dirs" or even use the "mcd" (menu change dir) command. You use this "cd" alias like "cd N" as well, where N is the index on the stack (given by "dirs" output). And pushd and popd work on this same stack.

For your .kshrc profile:

. /usr/share/ksh/fun/popd <<<< includes pushd as well **
. /usr/share/ksh/fun/dirs <<<< if you also want the custom cd + dirs

**ls -althr /usr/share/ksh/fun:

total 16K
-rwxr-xr-x 1 root root 2.5K Jun  6  2012 pushd
-rwxr-xr-x 1 root root 2.3K Jun  6  2012 dirs
lrwxrwxrwx 1 root root    5 Jan 19 23:43 popd -> pushd     <<<< symlink

These work great! (example)

trigen@ip-10-235-45-12:/etc/apache2> cd /var/log/
trigen@ip-10-235-45-12:/var/log> dirs
1) /var/log
2) /etc/apache2
3) /usr/local/src
4) ~
trigen@ip-10-235-45-12:/var/log> cd 2             <<<< If you have a directory named '2', use "cd ./2" :P
trigen@ip-10-235-45-12:/etc/apache2> mcd
1) /etc/apache2
2) /var/log
3) /usr/local/src
4) ~
Select by number or enter a name: 3

or what I was talking about:

trigen@ip-10-235-45-12:/home/trigen> cd /usr/local/lib
trigen@ip-10-235-45-12:/usr/local/lib> pushd .
/usr/local/lib ~ /usr/local/lib
trigen@ip-10-235-45-12:/usr/local/lib> cd /
trigen@ip-10-235-45-12:/> popd                 <<<< In this trivial example "cd -" (where - is previous dir) would also work.
/usr/local/lib ~ /usr/local/lib
Linux/Unix Comments (0)

Leave a Reply

Comment may not be visible immediately, because I process everything manually.**

**) I plan to automate this.., but it's on my ToDo since for ever..

Ray Burgemeestre
february 23th, 1984

C++, Linux, Webdev

Other interests:
Music, Art, Zen