31

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
1
  • 2
    Be aware that . /path/to/script sources the script! You don't need the period at all if you just want to run it. Nov 25, 2012 at 8:35

11 Answers 11

28

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)
4
  • 4
    Do you mean (cd /wherever/ ; sh script.sh)?  Why do you have a $ in front? May 24, 2018 at 7:08
  • 1
    I'd guess the $ is intended to be the command prompt?
    – mskfisher
    Sep 23, 2020 at 16:09
  • 1
    The $ or # is a "common" convention to indicate the prompt. It's also a way to prevent lusers from copy-pasting something dumb, maybe. Dec 2, 2020 at 5:04
  • The $ to prevent users copy/pasting something dumb is more of an annoyance to the people trying to double click to get the command than it saves dumb people. They'll just remove the "$" anyway. Also, isn't giving them the command the whole point in the first place? Sure if the command is delete 10000 dirs etc
    – James
    Dec 19, 2021 at 13:20
8

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

2
  • I would highly recommand option 2.
    – Bernhard
    Nov 25, 2012 at 11:04
  • Why?, it's a best practice or just taste?
    – Sergio
    Sep 7, 2014 at 4:42
6

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.

2
  • would not work if secure_path is set in /etc/sudoers file
    – l1zard
    Nov 24, 2012 at 23:09
  • this seems like the most straightforward method. also, perl /path/to/script for perl scripts (since he mentioned perl). May 12, 2020 at 16:24
4

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.

1
  • 1
    Typo: you mean .bashrc instead of .bachrc. Nov 25, 2012 at 14:35
1

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.

1

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.

1

Say you want to run ./script and the path is /home/test/stuff/

But the path you're currently in is /home/test/public_html/a/

Then you would need to do ../../stuff/./script

Which goes back 2 folders, then into into the folder there and run the script.

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.

0

It's better to modify your script to use its absolute path before addressing any relative files.

Of course for scripts we can do it conveniently and flexibly by keeping the dirname of the script in a variable before-hand.

For example, change:

cat needed_file

to:

SCRIPT_PATH=$(dirname "$0")
cat "${SCRIPT_PATH}/needed_file"
0

just run " sh + path "

sh /Desktop/Foldername/ExecutableFile or
./Desktop/foldername/Executable File

2
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Apr 1, 2023 at 10:44
  • Please see how to write a good answer and formatting. Code and commands are marked with the code brackets {} on the edit box toolbar, or enclosed in backticks. Also when answering an old question the new answer should bring something previously not suggested. This is already suggested here. Please check the Tour, Asking and Answering in Help center((superuser.com/help) and some q:s with accepted answers to learn how the site works. Apr 1, 2023 at 10:45
-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
2
  • (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. May 24, 2018 at 3:12
  • @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
    May 24, 2018 at 3:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .