Find out directory where command is located

so i have a script that i do not want copies of that script to be roaming around. i want that script to be in only one location on the filesystem, and whoever wants to use it should just link to it.

any idea on how to exit from a script if it is detected that the running version is a copy and not a link to the original??

my attempt so far:

#!/bin/sh
expectedDIR=/var/home/mon
actualdir=$(echo $0 | awk -F"/" '{print $1}')
if [ "${expectedDIR}" != "${actualdir}" ] ; then
echo "Running copies of this script is not allowed. please link to the original instead of copying!"
exit 2
fi

You could try something like this, using pwd and ls -l to determine the absolute pathname:

file=$(cd -P -- "${0%/*}" 2>/dev/null; pwd -P)/${0##*/}  # get the physical path name of the file that is being specified
while :                                                  # iterate through symbolic links to arrive at the actual directory
do
  ls=$(/bin/ls -l "$file") 
  case $ls in
    l*) file=${file%/*}/${ls##*-> } ;;                   # if the file is a symbolic link then follow it, by replacing
    *)  break ;;                                         # the file name with what the link points to, if not then break the loop
  esac
done
actualdir=${file%/*}

--
You can never force this of course, since one could copy the script and make an adjustment of the variable, but it may help to make users aware....

--
On Linux one could also use readlink , but this is a more general approach, which should also work on most Unix platforms...

1 Like

Hi,
Another way would check inode file, examples:
my file:

$ ls -l aa1.txt 
-rw-rw-r-- 2 disedorgue disedorgue 66 janv.  3 21:21 aa1.txt

Hard link of my file:

$ ls -l aa2.txt 
-rw-rw-r-- 2 disedorgue disedorgue 66 janv.  3 21:21 aa2.txt

Symbolic link of my file:

$ ls -l aa3.txt 
lrwxrwxrwx 1 disedorgue disedorgue 7 janv.  3 21:37 aa3.txt -> aa1.txt

A copy of my file:

$ ls -l aa4.txt 
-rw-rw-r-- 1 disedorgue disedorgue 66 janv.  3 21:50 aa4.txt

inode's files:

$ ls -1i aa*.txt
956473 aa1.txt
956473 aa2.txt
941974 aa3.txt
942170 aa4.txt

here, inode of aa3.txt and aa4.txt are differents, but aa3.txt is a symbolic link, so with ls option "-L":

$ ls -L1i aa*.txt
956473 aa1.txt
956473 aa2.txt
956473 aa3.txt
942170 aa4.txt

Now, just aa4.txt is different, but this is normal because it's a copy...

Regards.

cd -P

is limited to bash and ksh. The OP's script is a sh script:

#!/bin/sh
expectedDIR=/var/home/mon
actualdir=$(echo $0 | awk -F"/" '{print $1}')
if [ "${expectedDIR}" != "${actualdir}" ] ; then
echo "Running copies of this script is not allowed. please link to the original instead of copying!"
exit 2
fi

Yes. Linux conflates bash and sh. That doesn't make such usage portable.

Let us be very clear here. When doing tests like this with a shell script, sometimes you have to know what shell you're using. Claiming that cd -P can't be used in /bin/sh might or might not be true. If you're using a Linux system where /bin/sh is a link to bash , you can use cd -P . If you're using a Solaris system where /bin/sh is a legacy Bourne shell, you can't use cd -P , but you can't use $(command) either (you'd have to use `command` instead).

Furthermore, the awk script shown in the code above is going to return an empty string any time $0 expands to an absolute pathname for the script being executed and . otherwise. That is the basis of the problem that kept the script from doing what the submitter intended to do. But..., as has been said before, I'm not sure that I understand this thread. If someone copies a script and slightly modifies it for some reason (any reason), modifying the original script to see if it has been moved doesn't help. Anybody that can copy and modify the script can obviously and easily also remove any code that verifies that the script hasn't been moved or modified.

This is not correct. cd -P is part of the POSIX standard.

SYNOPSIS

cd [-L|-P] [directory]

cd -

cd: Synopsis.

It also works with ksh88, so the only (Bourne family) shell it will not work with is the classic Bourne shell...

So cd -P is in fact very portable...

Also, as Don Cragun noted, the OP used $( ... ) so it is clear that the OP is not using classic Bourne shell and that #!/bin/sh points to a POSIX type shell.

----

I agree as I noted in post #1. So if someone wants to circumvent this, it is very easy. The reason however, as I can see it, might be that you want to avoid a sprawl of the same script in a Company situation and to make users of the script aware that they should use the centrally maintained version by either using it directly or linking to it. If they want to bypass that, fine but then they should not complain if things break in the future..