Running a script from it's resident folder?

Let’s say I have a script named test1.sh that looks like this:

#!/bin/sh
PWD=$PWD/dirname $0
cat file1.txt

That script and the file file1.txt resides in a subdirectory named sub1. Then I run that script with the following command:

sh sub1/test1.sh

I was hoping that setting PWD would influence test1.sh to find and print the contents of file1.txt, but no. Since test1.sh was called from a directory level above sub1, it looks for file1.txt there.

Is there an easy way to make this work, that is to somehow set the environment for a script to run with all it’s references from the folder where it resides and not from where it was called?

If called with an absolute path, the path is in $0.

If called with a relative path, it can append $0 to the output of the pwd command.

But better still don’t use external text files in the shell script, you can often replace them with literal strings in the script or here documents. E.g.

somecommand <<EOS
data
data
data
EOS

IMHO you can not set the PWD parameter. It is set by the shell and contains: “The present working directory set by the **cd **command”. And that is (and should be) the only way to alter the PWD parameter.

The man page on the system differs from the one in my manual. It says:
“This variable shall represent an absolute pathname of the current working directory. Assignments to this variable may be ignored unless the value is an absolute pathname of the current working directory and there are no filename components of dot or dot-dot”.
Hm, sounds strange to me, I read this as: it can be assigned as it is what it already is.

My conclusion, use cd to change your working directory (and PWD will change to reflect this).

Well, the text file was just an example of relative reference. In my actual case I have several scripts in a directory structure calling each other. Always calling with an absolute path makes things inflexible, and the long pathnames messes up the code.

I could of course prepend the output of dirname $0 to every reference in all scripts. I was just hoping there was a way to change the environment to accomplish that automatically.

I am not sure I understand completely what your lay out is (in fact I am pretty sure I don’t :wink: ), but in a (may be) similar case, I start every script with setting variables to the different directories where scripts are:

DBSCRIPTS="/home/user/henk/databese/bin/"
LOUSYSCRIPTS="/home/henk/donotknow/"

and then call a script:

${DBSCRIPTS}dbopen

This (long) range of statements can be put in a seperate file (containing just this AB=/a/b/c/ things), which you then can call in all your scripts with:

. /home/henk/thebasics/scriptplaces

(Mind the DOT SPACE in the beginninmg).
You then have a central place where you can edit a directory path and it will be known by all scripts.

Hope this gives some inspiration.

And sorry for using ksh syntax, much more readable to me, I never use the pwd but rather $(pwd).

Yes it does. That will most likely be the way I do it.

Though I still think an option to the shell telling it to execute a command file from where it resides (as opposed to where it was called from) would be a useful feature. Any shell developers reading this? :wink:

You can execute a program that resides in the same directory where the shell program that calls that program resides by:

basename ${0}/program

when it is that is what you mean.

This is in fact what ken_yap said in post #2, but a bit more elaborate.

:confused: well… correct me if I’m wrong but doesn’t basename strip leading directory path from it’s argument, so that:

basename ${0}/program

would simply become:

program

which of course would work as long as the calling shell script and the called program reside in the same directory (as you said). But if called from another directory, as was my original intent, program would not be found, right? :\

I think hcw meant to write

dirname $0

dirname in a sense is the counterpart of basename.

Am I dumb. Of course I wanted to type

$(dirname ${0})/program

or

`dirname $0`/program

So why did I not type what I want?? >:(
That is because I am only human and no computer.
I hope you will forgive me for typing this big nonsense :shame:

But of course, no problem :slight_smile: All your input in this matter is welcome.