1

So I am trying to make a count-down timer in bash, where I have two files-
One for my alarm functionalities
The other for displaying the numbers on the terminal

So my directory structure is somewhat like this-
Parent Dir
|____ alarm.sh
|____ views.sh

My first attempt was to make a $directory variable and get the path-

directory=$PWD

However, if I execute my script from another directory, it creates an issue, since $directory would be the new directory and not the one the script is in.

I then tried using the readlink command-

path=$(dirname "$(readlink -f "$0")")
. $path/views.sh

This, however, creates problems. While it does work, following links and all, in GNU/Linux bash, it does not in the OSX bash (which I think is BSD, but I may be wrong).

So my basic question is- How to refer to views.sh from alarm.sh? And is there a way to do so without going through the hassle of finding the parent directory name?

aadinaik
  • 51
  • 1
  • 6

3 Answers3

0

May be the simplest way to tackle this would be to add the directory of alarm.sh to PATH in view.sh:

PATH=$PATH:/path/to/alarm
source alarm.sh ...

If you have many scripts that need this kind of referencing or if you have many directories that need to be added to the PATH, then it is prudent to write an init script that sets up the PATH (and other environment variables as required) appropriately. And then, you can call the init script in all your scripts:

source /path/to/init.sh # set PATH etc
source alarm.sh

For your immediate requirement of deriving alarm.sh's PATH relative to the directory of view.sh (see this post), you could do this:

this_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
cd "$this_dir"
source alarm.sh # (or source ./path/to/alarm.sh or source ../path/to/alarm.sh)

Remember, a good script should never make any assumptions about which directory it is in or the current directory of the calling program.

codeforester
  • 39,467
  • 16
  • 112
  • 140
  • I'll surely consider the init script suggestion... It seems to be the easiest way out. As far as `this_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"` goes, it is unable to follow symbolic links, so it may cause an issue if the user is using symlinks to execute the command. – aadinaik Oct 28 '17 at 14:08
  • Well, I did use `this_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" source $this_dir/views.sh` which did not work. The way I set up my commands was that I created a symlink called alarm in /usr/bin pointing to alarm.sh which was in a subdirectory of the home directory. Upon reaching the above set of commands, it simply says `/usr/bin/views.sh: No such file or directory` – aadinaik Oct 28 '17 at 17:04
  • The script does work with the readlink alternative using the same symlink, so I think the symlink should be fine... – aadinaik Oct 29 '17 at 12:06
0

For fortune this problem is simple to fix.

if the two files are in the same directory, you can import without get the fullpath of the files.

Example:

Then, if you want to use the functions and variables which are defined in views.sh in your alarm.sh you can "import" like this:

#views.sh
TIME=60

# alarm.sh
source views.sh


echo "this is a views.sh variable: $TIME"

Other solution, if the scripts are in different folders, you can do like this:

#views.sh
TIME=60

# alarm.sh
source $(readlink -f views.sh)


echo "this is a views.sh variable: $TIME"

the readlink command gives you the fullpath of the file without symbolic links. This dont have to give you problems on OSX.

I dont recommend you to use this form:

path=$(dirname "$(readlink -f "$0")"
#

Example of dirname: dirname: gives you the route to a file without translate the symbolic links readlink -f: gives you the full path with the translation of the symbolic links.

I have this files:

├── files -> folder/folder2

├── folder

│   └── folder2

│       └── file_001.txt

As you can see "files" is a symbolic link. Then if I do dirname:

user@host:/$ dirname home/user/files/file_001.txt

home/user/files

But If I use readlink:

user@host:/$ readlink -f home/user/files/file_001.txt

/home/user/folder/folder2/file_001.txt

A.Villegas
  • 462
  • 7
  • 18
  • Could you please elaborate as to why `source $(readlink -f views.sh)` is more preferable than `path=$(dirname "$(readlink -f "$0")"`? – aadinaik Oct 28 '17 at 14:10
  • The readlink command gives you the full path of the file without symbolic links, but dirname gives you the route to the file and do not translate de symbolic links. For these, If you use readlink is not necessary use dirname. In a few minutes I post here an example for you – A.Villegas Oct 28 '17 at 14:25
  • Please do so! Also, I'd like a solution which will work even on OSX. I do not know about now, but around 3 months back, I had tested the script using readlink on my friend's MacBook and it gave an error, despite working fine on my Ubuntu distribution (17.04). – aadinaik Oct 28 '17 at 17:08
0

You can try like that but views.sh must be unique. I think it's the same with readlink

# alarm.sh
viewer="$(find ../ -name views.sh)"
source "$viewer"
echo "this is a views.sh variable: $TIME"
ctac_
  • 2,413
  • 2
  • 7
  • 17