Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!husc6!necntc!ncoast!allbery From: allbery@ncoast.UUCP Newsgroups: comp.sources.misc Subject: directory stack manipulation routines for bourne shell Message-ID: <4563@ncoast.UUCP> Date: Wed, 23-Sep-87 22:39:22 EDT Article-I.D.: ncoast.4563 Posted: Wed Sep 23 22:39:22 1987 Date-Received: Sat, 26-Sep-87 11:12:11 EDT Sender: allbery@ncoast.UUCP Organization: Drexel University, Phila., Pa. Lines: 194 Keywords: pushd, popd, dirs ... Approved: allbery@ncoast.UUCP X-Archive: comp.sources.misc/8709/15 Hello ( is there a better greeting that does not sound so boring? ) - Having been working for a long time under csh and being accustomed to the commands pushd and popd, I was saddened to find that these commands were not avaiable under my version of Microport Unix System V (version 2.2). I had just come across ksh routines to do this and thought, hey, what a wonderful way to spend a few hours instead of doing something that I should be doing (like real work 8-). The result is my first csh program (all other shell programs where written using the bourne shell). It is used with a few (four) alias-es and manages a directory stack. Hope you find it useful. If you decide to give this a try, wait until using it before reading the next sentence. You shouldn't be reading this unless you've tried it already - okay - experienced it? - well ... it may not be incredibly fast, but the object was to learn a bit of the c shell. Rickers ..!drexel!rickers ==========c=u=t====h=e=r=e=====================c=u=t====h=e=r=e========= #!/bin/csh # # (-8 tab stops should be at every four for easy readibility 8-) # # dirstack -- c shell script to manipulate a directory stack # written by rickers, august 29, 1987 # # Permission is granted to do what you wish with this code. Happily # placed in the public domain. No copyrights - no nutin'. # # Description of routines: # init -- initializes the environment so that the routines can work. # dirs -- prints out directory stack. # pushd -- push the current directory and change to that specified # popd -- pop a directory and change to it # # These routines pattern themselves after the same functions of the # C shell, with a few exceptions. Idea to write this script taken from # ksh script originally written by David C. Stewart, and modified to # work under MKS tookkit ksh by Keith Ericson, both of Tektronix Inc. # # To use, some aliases are needed. These follow. # set dirstack=/usr/local/lib/dirstack # alias initds "set argv=(init \!*); source $dirstack; set argv" # alias dirs "set argv=(dirs \!*); source $dirstack; set argv" # alias pushd "set argv=(pushd \!*); source $dirstack; set argv" # alias popd "set argv=(popd \!*); source $dirstack; set argv" # unset dirstack # # This file should be placed in a known directory. The dirstack variable # is just to make the alias look a bit neater. # # You may be pondering with the question "why did he do it this way?" when # i figure it out, i will let you know (maybe). it just seemed the thing to # do. note these need routines need to be executed using source. it is # faster (it does not invoke another shell) and it makes the variable # available to the shell. # # Oh, btw, the other reason this was written, was to make up for a lacking # csh under Microport Unix System V 2.2. # # # Depending on argv[1], goto a certain spot in the script and execute # goto $argv[1] init: # the current directory stack depth set ddepth=1 # dstack is the directory stack, set to a max depth of 20 set dstack=(`pwd` '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '') goto finish # # dirs is equivalent (almost) to the csh command `dirs'. It prints out # the stack, current directory first, followed by top of stack, and the # rest of the stack. it fmt-s the output so it looks nice and does not # get fold-ed at 80 chars. It is a bit slow - oh well, so are the rest # of the routines. # dirs: set i=$ddepth if ( $i == 1 ) set dstack[1]=`pwd` cp /dev/null /tmp/$$ while ($i > 0) echo $dstack[$i] >> /tmp/$$ @ i = $i - 1 end sed "s,$home,\~,g" /tmp/$$ | fmt ; rm /tmp/$$ goto finish # # pushd is stretching from the csh definition of pushd. given one arg, # it pushes the current directory on the stack, and changes to the # specified directory. now comes the kludge. to specify a buried # directory, use the syntax: pushd + n. note the space between the # plus sign and the number. It is there to make life easier and faster. # you wouldn't want it any other way now, would you? also, the way it # works is different from the way my pushd works (under 4.2BSD). It # exchanges the current directory and the specified directory, making # the specified directory current. note that the number is offset to # the current directory on the dirs print-out ( + 1 is top of stack ). # also note that the current directory is not on the top of the stack. # pushd given with no arguments is the exact same as pushd + 1, and # exchanges the current directory with the top to the stack. # pushd: switch ($#argv) case 1: if ( $ddepth < 2 ) then echo pushd: No other directory. goto finish else @ i = $ddepth - 1 set temp=$dstack[$i] set dstack[$i]=$dstack[$ddepth] set dstack[$ddepth]=$temp cd $dstack[$ddepth] endif breaksw case 2: if ( $ddepth == 1 ) set dstack[1]=`pwd` @ ddepth++ cd $argv[2] set dstack[$ddepth]=`pwd` breaksw case 3: @ i = $argv[3] @ i = $ddepth - $i set temp=$dstack[$i] set dstack[$i]=$dstack[$ddepth] set dstack[$ddepth]=$temp cd $dstack[$ddepth] breaksw default: echo usage: pushd \| pushd name \| pushd +n goto finish endsw goto dirs # # popd is stretching from the csh definition of popd. given no args, # it pops one directory from the stack and makes it current, assuming # that one exists. again a kludge (same one). to specify a buried # directory, use the syntax: popd + n. note the space between the # plus sign and the number. same old argument as above. but, ha, this # one actually works like the csh popd. oh well, there goes the large # deviation. what this action does is removes the specifed directory # from the directory stack. again, note that the number is offset to # the current directory on the dirs print-out ( + 1 is top of stack ). # also note that the current directory is not on the top of the stack, # although it is the first printed in the dirs output. # popd: if ( $ddepth == 1 ) then echo popd: Directory stack empty. goto finish else switch ($#argv) case 1: breaksw case 2: echo usage: popd \[ + n \] goto finish breaksw case 3: if ( ($argv[3] < 1) || ($argv[3] >= $ddepth) ) then echo popd: Illegal value. goto finish endif @ i = $ddepth - $argv[3] while ( $i < $ddepth ) @ temp = $i + 1 set dstack[$i]=$dstack[$temp] @ i = $i + 1 end breaksw endsw endif @ ddepth-- cd $dstack[$ddepth] goto dirs # # finishup is the generic get outta here routine. # finish: unset i unset temp