[comp.unix.questions] cd function

pete@wvus.wciu.edu (Pete Gregory) (02/16/91)

Hi, netters.  Here's a good one for you...

My login shell is /bin/sh (I guess I should say I'm running AT&T V.3.2,
actually Unisys PTX 1.1.1 for those who care), and I want my prompt
to include my current working directory.

I know how to do this in csh: alias cd 'chdir $1;set prompt="$cwd"' ,
but I can't figure it out in sh.

What I've tried:  putting a function called 'cd' in .profile:

cd()
{
   cd $*
   PS1="`pwd`"
}

...but alas this doesn't work because the shell uses its own internal cd
instead of running my function.  I've also tried a shell script called cd,
but this doesn't work for two reasons: 1) sh still uses its internal cd,
and 2) the shell's pwd changes, but not the parent, my login shell.

What I want to do is REPLACE sh's 'cd' with one of my own (but which still
uses sh's 'cd').  Well, what I REALLY want to do is get the prompt to
always show my current working directory (ie. `pwd`).

Any and all insights appreciated.
 
Pete Gregory, UNIX SA  |  pete@wvus.wciu.edu                  |
World Vision USA/ISD   |  wciu!wvus!pete                   ___|___
919 W. Huntingon Dr.   |  Voice: 818/357-7979 x3347           |
Monrovia, CA  91016    |  FAX:   818/303-6212                 |
                                                              |
Romanian orphans need our help!  Call 1-800-777-1229

gwyn@smoke.brl.mil (Doug Gwyn) (02/18/91)

In article <2PyFX1w163w@wvus.wciu.edu> pete@wvus.wciu.edu (Pete Gregory) writes:
>Hi, netters.  Here's a good one for you...

Yes, this is one of the better recent questions.

>What I've tried:  putting a function called 'cd' in .profile:
>cd()
>{
>   cd $*
>   PS1="`pwd`"
>}
>...but alas this doesn't work because the shell uses its own internal cd
>instead of running my function.

This is properly viewed as a deficiency in the support provided by the
Bourne shell, which is why 8th Edition UNIX added the "builtin" shell
builtin.  BRL (mostly Doug Kingston) implemented "builtin" in the
version of the Bourne shell that I maintain and make available upon
request to properly-licensed sites.  (UNIX System V Release 2.0 or
later source license required.)  Our shell has many independently-
implemented features similar to those found in other shells such as
the Korn shell, although different in detail.  (We like ours better,
and were inspired by the 8th Edition UNIX shell features.)  Here is
how my startup "dot files" redefine the "cd" command; doing what you
were attempting is trivial, but mine also takes care of supporting
a form of "working directory history" and providing host and current
working directory information in either the $PS1 prompt or in a window
banner (title), depending on the type of terminal being used.  It will
undoubtedly grow larger when I add support for X-Windows.  (I'm
considering introducing a separate function for banner manipulation.)
While you couldn't use this example directly, out of the context that
I establish for my shell working environment, it does show that the
basic idea is workable, if your shell provides the proper support.

Until and unless you find a better shell, you might consider naming
your function something like "cwd" and getting into the habit of using
that instead of typing "cd".

#	If the "builtin" command (BRL shell) doesn't exist, the following
#	will not be invoked (always get built-in "cd"), so its use of
#	"builtin" is not a problem.
cd(){
	PREVDIR="$CWD"
	if [ $# -lt 1 ]
	then	builtin cd
	else	builtin cd "$1"
	fi
	CWD=`pwd` export CWD
	# exported so interactive subshells can cd $CWD to outwit symbolic links
	set +u
	if [ "$CWD" = "$HOME" ]
	then	PFX="$HOST" PS1=
	else	PFX="$HOST": PS1=`echo "$CWD" |
			sed -e "s!^$HOME!~!" -e "s!^/usr/src/s5!~sys5!"`
	fi
	if [ "$TERM" = att630 -o "$TERM" = tty630 ]
	then	if [ -z "$PS1" ]
		then	PS1=:~
		fi
		echo '\033[?'`expr "$PFX$PS1" : '.*'`";0v$PFX$PS1\c"
		PFX= PS1=
	elif [ "$MYXBAN" ]
	then	case "$TERM" in
		sun)
			echo "\033]L $HOST\033\\\\\c"
			echo "\033]l $PFX$PS1\033\\\\\c"
			PFX= PS1=
			;;
		*5620*)	# "myx" assumed; ~/.myxban -> $DMD/local/bin/myxban
			if [ -z "$PS1" ]
			then	PS1='~'
			fi
			if [ -x ~/.myxban ]
			then	~/.myxban -l " $HOST"
				~/.myxban -r "$HOST "
				~/.myxban -c "$PS1"
			fi
			PFX= PS1=
			;;
		esac
	fi
	PS1="$PFX$PS1"'$ '
	unset PFX
	set -u
}

mike (02/18/91)

In an article, wvus.wciu.edu!pete (Pete Gregory) writes:
>My login shell is /bin/sh (I guess I should say I'm running AT&T V.3.2,
>actually Unisys PTX 1.1.1 for those who care), and I want my prompt
>to include my current working directory.

Well, unless your version of the shell allows a builtin function to be 
superceded, or you have the source (example: BaSH) then you have to resort
to ugliness.

WARNING: Ugliness is to follow.  If you are easily offended by ugly
         kludges to routine problems, do not proceed further.


Take your favorite binary editor (or use adb if you're hard-up), and walk
through the binary for /bin/sh; replace 'cd' with 'xx'.  Then your function
will work ...

	cd() {
		xx $*
		PS1="`pwd`> "
		}

Yep.  I told you it was ugly.

Cheers,
-- 
Michael Stefanik, MGI Inc., Los Angeles| Opinions stated are not even my own.
Title of the week: Systems Engineer    | UUCP: ...!uunet!bria!mike
-------------------------------------------------------------------------------
Remember folks: If you can't flame MS-DOS, then what _can_ you flame?

boyd@necisa.ho.necisa.oz.au (Boyd Roberts) (02/19/91)

The V8 shell is the way to go:

    cd()
    {
	builtin cd $1 &&
	case "$1" in
	'')
	    PS1="% " ;;
	..|*/..)
	    PS1="`basename \`/bin/pwd\``% " ;;
	/)
	    PS1="/% " ;;
	*/*)
	    PS1="`basename $1`% " ;;
	*)
	    PS1="$1% " ;;
	esac
    }

Of course, as Doug said, you need `builtin' or you have to rename the function.


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''

chet@odin.INS.CWRU.Edu (Chet Ramey) (02/19/91)

In article <2023@necisa.ho.necisa.oz.au> boyd@necisa.ho.necisa.oz.au (Boyd Roberts) writes:
>The V8 shell is the way to go:
>
>    cd()
>    {
	[ ... ]
>    }

Bash will do this too:

cd ()
{
    builtin cd ${1+"$@"} && xtitle $HOST: $PWD
}
-- 
Chet Ramey				``Now, somehow we've brought our sins
Network Services Group			  back physically -- and they're
Case Western Reserve University		  pissed.''
chet@ins.CWRU.Edu		My opinions are just those, and mine alone.