Running scripts from another directory

10

2

Quite often, the script I want to execute is not located in my current working directory and I don't really want to leave it.

Is it a good practice to run scripts (BASH, Perl etc.) from another directory? Will they usually find all the stuff they need to run properly?

If so, what is the best way to run a "distant" script? Is it

. /path/to/script

or

sh /path/to/script

and how to use sudo in such cases? This, for example, doesn't work:

sudo . /path/to/script

Desmond Hume

Posted 2012-11-24T22:35:59.183

Reputation: 1 870

Be aware that . /path/to/script sources the script! You don't need the period at all if you just want to run it. – gniourf_gniourf – 2012-11-25T08:35:43.947

Answers

14

sh /path/to/script will spawn a new shell and run she script independent of your current shell. The source (.) command will call all the commands in the script in the current shell. If the script happens to call exit for example, then you'll lose the current shell. Because of this it is usually safer to call scripts in a separate shell with sh or to execute them as binaries using either the full (starting with /) or relative path (./). If called as binaries, they will be executed with the specified interpreter (#!/bin/bash, for example).

As for knowing whether or not a script will find the files it needs, there is no good answer, other than looking at the script to see what it does. As an option, you could always go to the script's folder in a sub-process without leaving your current folder:

$(cd /wherever/ ; sh script.sh)

Ярослав Рахматуллин

Posted 2012-11-24T22:35:59.183

Reputation: 9 076

3Do you mean (cd /wherever/ ; sh script.sh)?  Why do you have a $ in front? – G-Man Says 'Reinstate Monica' – 2018-05-24T07:08:13.810

7

You can definitely do that (with the adjustments the others mentioned like sudo sh /pathto/script.sh or ./script.sh). However, I do one of a few things to run them system wide to not worry about dirs and save me useless extra typing.

1) Symlink to /usr/bin

ln -s /home/username/Scripts/name.sh /usr/bin/name

(be sure there is no overlapping name there, because you would obviously override it.) This also lets me keep them in my development folders so I can adjust as necessary.

2) Add the Scripts dir to your path (using .bash_profile - or whatever.profile you have on your shell)

PATH=/path/to/scripts/:$PATH

3) Create Alias's in the .bash_profile in ~/.bash_profile add something like:

alias l="ls -l"

As you can tell, the syntax is just alias, digits you want to act as a command, the command. So typing "l" anywhere in the terminal would result in ls -l If you want sudo, just alias sl="sudo ls -l" to note to yourself l vs sl (as a useless example).

Either way, you can just type sudo nameofscript and be on your way. No need to mess with ./ or . or sh, etc. Just mark them as executable first :D

nerdwaller

Posted 2012-11-24T22:35:59.183

Reputation: 13 366

Why?, it's a best practice or just taste? – Sergio – 2014-09-07T04:42:30.497

I would highly recommand option 2. – Bernhard – 2012-11-25T11:04:18.217

3

I usually do like you say

sh /path/to/script

And to run it as root/superuser

sudo sh /path/to/script

Your current directory only matters if the scripts assumes you are in the same folder as it. I would assume most scripts don't do this and you are save to run it like above.

Bolli

Posted 2012-11-24T22:35:59.183

Reputation: 382

would not work if secure_path is set in /etc/sudoers file – l1zard – 2012-11-24T23:09:58.483

3

I usually keep my scripts in /usr/local/bin or /usr/local/sbin/ (if the script needs root privileges) where, according to the Filesystem Hierarchy Standard (FHS), they belong.

All you have to do is to make sure these two directories are added to your PATH. You can do this by editing your $HOME/.bashrc file and adding this line:

export PATH=$PATH:/usr/local/sbin:/usr/local/bin

If you want to be able to execute a script as root via sudo, you have to add these directories to the variable secure_path in your /etc/sudoers.

Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

Editing this file is done by running visudo which ensures you don't have any mistakes.

l1zard

Posted 2012-11-24T22:35:59.183

Reputation: 933

Typo: you mean .bashrc instead of .bachrc. – gniourf_gniourf – 2012-11-25T14:35:56.163

0

If you have scripts lying around that you need to run often, and they depend on their location for finding resources you can easily do this by just combining commands in an alias like this.

alias run-script="cd /home/user/path/to/script/ && bash script.sh"

This way you don't have to alter anything else to make it work.

EvR2f

Posted 2012-11-24T22:35:59.183

Reputation: 31

0

Not sure why no one has suggested this one, but it's super easy! I've Googled a few times and couldn't find this exact answer I'm giving so I'd thought I'd share. IMO, this but the best solution, also the easiest one, for me anyway, however others may feel and do things differently.

# Place this somewhere in your .bashrc/.bash_profile/etc and edit as you see fit

YOURCOMMAND () {
  cd /path/to/directory/containing/your/script/ && ./YOURSCRIPT
}

First the 'cd' command telling it the directory of the scripts location. Then '&&' so that you can tie it after excuting the next command. Finally open your script just as you would would execute it within terminal! Saved your in your BASH file and takes 5 seconds to setup.

Hope this helped someone.

AnonymousX

Posted 2012-11-24T22:35:59.183

Reputation: 1

0

I'm not sure it works like this in linux, assuming it doesn't if no-ones suggested it. But instead of using ././ to go back directories. Can you use quotes to give it an absolute path? Maybe it doesn't give you access to the whole drive to even be able to do that actually come to think of it.

Codezilla

Posted 2012-11-24T22:35:59.183

Reputation: 828

-1

Ancient question, but a timeless one.

The solution I've consistently seen is to have a $HOME/bin directory and put it first in $PATH (via ~/.bashrc if it isn't already there; on some systems ~/bin is first in $PATH by default). Dropping scripts in there for execution or symlinks to scripts/executables elsewhere is the simple way to deal with path issues that shouldn't affect the system or other users.

If a script requires additional resources that can be found relative to its own location (not uncommon) then the envvar $BASH_SOURCE is used. $BASH_SOURCE always contains the absolute path to the currently running script itself, regardless the value of $PWD.

Consider the following:

ceverett@burrito:~$ echo $PATH
/home/ceverett/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

So we can see that $HOME/bin is first in $PATH, so whatever I put in ~/bin will run. I have a demonstration script called ~/bin/findme:

#!/bin/bash

echo "Running from $BASH_SOURCE"

This can be used to get the absolute path to the running script's location.

ceverett@burrito:~$ findme
Running from /home/ceverett/bin/findme
ceverett@burrito:~$ cd foo
ceverett@burrito:~/foo$ findme
Running from /home/ceverett/bin/findme
ceverett@burrito:~/foo$ cd /
ceverett@burrito:/$ findme
Running from /home/ceverett/bin/findme

zxq9

Posted 2012-11-24T22:35:59.183

Reputation: 99

(1) While this appears to be useful information, the question didn’t ask how to *write* scripts that use resources relative to their own location; it asked about running scripts. (2) I’m not sure how your second paragraph addresses the question.  Are you suggesting that, if I write a script and Desmond wants to run it, he should link it into his private bin directory?  That seems cumbersome.  (3) Also, it breaks location independence.  If /home/desmond/bin/foo is a link to my script, then BASH_SOURCE will be /home/desmond/bin/foo, and the script won’t be able to find its resources. – G-Man Says 'Reinstate Monica' – 2018-05-24T03:12:28.897

@G-Man (1) The user didn't provide much context. Whenever this question has been asked of me over the last 30 years it has always been in the context a user (usually a new sysop or developer) running a mix of his own and other acquired scripts to automate trivial tasks, so I answered it that way. This does assume a bit of scripting knowledge on the part of the user asking. (2) System-wide scripts are usually installed in /bin or a known location in /opt. (3) Location independence is exactly what this preserves when writing an inter-dependent collection of personal scripts. – zxq9 – 2018-05-24T03:27:54.113