views:

197

answers:

5

I have shell script which starts with:

sdir=`dirname $0`
sdir=`(cd "$sdir/"; pwd)`

And this usually gets expanded (with 'sh -h') into

++ dirname /opt/foo/bin/bar
+ sdir=/opt/foo/bin
++ cd /opt/foo/bin/
++ pwd
+ sdir=/opt/foo/bin

but for single user for single combination of parameters in expands into (note two lines at the result sbin value)

++ dirname bin/foo
+ sdir=bin
++ cd bin/
++ pwd
+ sdir='/opt/foo/bin
/opt/foo/bin'

I tried different combinations but was not able to reproduce this behavior. With different input parameters for that user it started producing correct single line result. I am new to shell scripting, so please advice when such (cd X; pwd) can return two line. it was observed on CentOS, but not sure it that matters. Please advice.

+1  A: 

It's possible that user has some funky alias for "cd". Perhaps you could try making it do "/usr/bin/cd" (or whatever "cd" actually runs by default) instead.

David M. Karr
cd is a shell built-in; there is no separate executable because it must be performed by the shell itself. (cd in a sub-process doesn't affect the parent process). Nevertheless, the 'alias for cd' item is plausible. Fix by unalias, probably.
Jonathan Leffler
A: 

Some people alias pwd to "echo $PWD". Also, the pwd command itself can either be a shell built-in or a program in /usr/bin. Do an "alias pwd" and "which pwd" on both that user and any user that works normally.

Paul Tomblin
+5  A: 

The culprit is cd, try this instead

sdir=`dirname $0`
sdir=`(cd "$sdir/" >/dev/null; pwd)`

This happens because when you specify a non absolute path and the directory is found in the environment variable CDPATH, cd prints to stdout the value of the absolute path to the directory it changed to.

Relevant man bash sections:

       CDPATH The  search  path  for  the  cd command.  This is a
              colon-separated list of directories  in  which  the
              shell  looks  for destination directories specified
              by the cd command.  A sample value is ``.:~:/usr''.

       cd [-L|-P] [directory]

              Change the current working directory to directory. If 
              directory is not given, the value of the HOME shell 
              variable is used. If the shell variable CDPATH exists,
              it is used as a search path. If directory begins with a slash, 
              CDPATH is not used.

              The -P option means to not follow symbolic links; symbolic 
              links are followed by default or with the -L option. If 
              directory is ‘-’, it is equivalent to $OLDPWD.

              If a non-empty directory name from CDPATH is used, or if ‘-’ 
RELEVANT  -\  is the first argument, and the directory change is successful, 
PARAGRAPH -/  the absolute pathname of the new working directory is written 
              to the standard output.

              The return status is zero if the directory is successfully 
              changed, non-zero otherwise. 

       OLDPWD The  previous  working  directory  as set by the cd
              command.

Vinko Vrsalovic
+1  A: 

CDPATH is a common gotcha. You can also use "unset CDPATH; export CDPATH" to avoid the problem in your script.

Chris Quenelle
A: 

Try this:

sdir=$( cd $(dirname "$0") > /dev/null ; pwd )

It's just a single line and will keep all special characters in the directory name intact. Remember that on Unix, only two characters are illegal in a file/dir name: 0-byte and / (forward slash). Especially, newlines are valid in a file name!

Aaron Digulla