1195

I have two shell scripts, a.sh and b.sh.

How can I call b.sh from within the shell script a.sh?

4
  • 10
    Can you give some specifics: which OS and which shell(s) or are you just talking about that problem in principle?? Example code would be helpful as well. Commented Dec 2, 2011 at 7:07
  • 2
    One issue I was having was that b.sh did not have executable permissions. It might be a good thing to check. Commented Mar 28, 2017 at 12:57
  • 2
    Append ./ before the script name, example, instead: b.sh, use: ./b.sh Commented Jul 2, 2018 at 14:02
  • 3
    If anyone keeps getting No such file or directory error stackoverflow.com/a/2920431/1356559 Commented Aug 15, 2018 at 1:10

18 Answers 18

1440

There are a couple of different ways you can do this:

  1. Make the other script executable with chmod a+x /path/to/file, add the #!/bin/bash line (called shebang) at the top, and the path where the file is to the $PATH environment variable. Then you can call it as a normal command;

  2. Or call it with the source command (which is an alias for .), like this:

    source /path/to/script
    
  3. Or use the bash command to execute it, like:

    /bin/bash /path/to/script
    

The first and third approaches execute the script as another process, so variables and functions in the other script will not be accessible.
The second approach executes the script in the first script's process, and pulls in variables and functions from the other script (so they are usable from the calling script). It will of course run all the commands in the other script, not only set variables.

In the second method, if you are using exit in second script, it will exit the first script as well. Which will not happen in first and third methods.

Sign up to request clarification or add additional context in comments.

12 Comments

Remember to change format/encoding of executable files in unix if they are created in DOS and then uploaded to unix environment -> dos2unix <script name>
Also, note that the scope of each script is the top level of your project's directory - if ./.git/hooks/pre-commit has source foo, you had better have ./foo!
@user528025 . is not an alias for source, but rather the other way around. source is a bash extension, while . works in any POSIX compatible shell.
@OhadSchneider In my case it was desirable to exit the script if the called script exited.
If both of your scripts are in the same directory, but still you are not sure where you're calling from, than you will have to construct the path to your script by first finding the script dir SCRIPT_DIRECTORY="$(dirname $(realpath "$0"))", and then calling it: source $SCRIPT_DIRECTORY/script.sh.
|
318

Check this out.

#!/bin/bash
echo "This script is about to run another script."
sh ./script.sh
echo "This script has just run another script."

7 Comments

This assumes that script.sh is in the same directory as the whatever script is running. If you wanted to call a script somewhere else, you would say sh <path to script>/script.sh
This also uses two shells, bash and sh. Even when sh is in fact bash it doesn't behave the same. If you're using #!/bin/bash then you probably want to use bash script.sh (or just ./script.sh to use that scripts's hashbang).
Kept getting permission denied error even when I set the chmod +x to the .sh file. Any suggestions?
@isaacweathers try chmod 777
@isaacweathers This indicates your user is not authorized, so you need to use sudo as in sudo chmod +x
|
215

There are a couple of ways you can do this. Terminal to execute the script:

#!/bin/bash
SCRIPT_PATH="/path/to/script.sh"

# Here you execute your script
"$SCRIPT_PATH"

# or
. "$SCRIPT_PATH"

# or
source "$SCRIPT_PATH"

# or
bash "$SCRIPT_PATH"

# or
eval '"$SCRIPT_PATH"'

# or
OUTPUT=$("$SCRIPT_PATH")
echo $OUTPUT

# or
OUTPUT=`"$SCRIPT_PATH"`
echo $OUTPUT

# or
("$SCRIPT_PATH")

# or
(exec "$SCRIPT_PATH")

All this is correct for the path with spaces!!!

6 Comments

What are their differences? Why one, why another?
. "$SCRIPT_PATH" is preferred
I can just add that these are not all equivalent, e.g. sh "$SCRIPT_PATH" and bash "$SCRIPT_PATH" will not run #!/usr/bin/expect script, whereas just "$SCRIPT_PATH" will.
If you need to pass arguments into the second script, "$SCRIPT_PATH", source, and . don't work that I can see. ./, /bin/bash, or the shorter bash all work though.
Note that 1-3 need the script to be executable while 4 for example does not. I think, this should be included/edited in the answer, right?
|
71

The answer which I was looking for:

( exec "path/to/script" )

As mentioned, exec replaces the shell without creating a new process. However, we can put it in a subshell, which is done using the parantheses.

EDIT: Actually ( "path/to/script" ) is enough.

5 Comments

This seems pretty convoluted. Why not just call it with /path/to/script? I don't see the need for exec at all here?
The subshell isn't needed either since you are not execing.
how would you execute this script with arguments?
If you want to still capture the output of the sub-script try $(source "path/to/script")
41

If you have another file in same directory, you can either do:

bash another_script.sh

or

source another_script.sh

or

. another_script.sh

When you use bash instead of source, the script cannot alter environment of the parent script. The . command is POSIX standard while source command is a more readable bash synonym for . (I prefer source over .). If your script resides elsewhere just provide path to that script. Both relative as well as full path should work.

Comments

21

Depends on. Briefly... If you want load variables on current console and execute you may use source myshellfile.sh on your code. Example:

#!/bin/bash
set -x
echo "This is an example of run another INTO this session."
source my_lib_of_variables_and_functions.sh
echo "The function internal_function() is defined into my lib."
returned_value=internal_function()
echo $this_is_an_internal_variable

set +x

If you just want to execute a file and the only thing intersting for you is the result, you can do:

#!/bin/bash
set -x
./executing_only.sh
bash i_can_execute_this_way_too.sh
bash or_this_way.sh
set +x

2 Comments

Note that source is a bash-specific feature. The standard bourne shell only has . (e.g. . other_script.sh).
For the difference between sh and bash, you can consider some answers of this U&L question. For example with the read command, there is a big difference between the two.
16

You can use /bin/sh to call or execute another script (via your actual script):

 # cat showdate.sh
 #!/bin/bash
 echo "Date is: `date`"

 # cat mainscript.sh
 #!/bin/bash
 echo "You are login as: `whoami`"
 echo "`/bin/sh ./showdate.sh`" # exact path for the script file

The output would be:

 # ./mainscript.sh
 You are login as: root
 Date is: Thu Oct 17 02:56:36 EDT 2013

3 Comments

Surely this will run showdate.sh under /bin/sh rather than /bin/bash?
i have tried with "/bin/sh ./showdate.sh", "/bin/bash ./showdate.sh", "./showdate.sh" and run the file: mainscript.sh and got same output.
For the difference between sh and bash, you can consider some answers of this U&L question. For example with the read command, there is a big difference between the two.
13

First you have to include the file you call:

#!/bin/bash
. includes/included_file.sh

then you call your function like this:

#!/bin/bash
my_called_function

Comments

12

Simple source will help you. For Ex.

#!/bin/bash
echo "My shell_1"
source my_script1.sh
echo "Back in shell_1"

Comments

11

Just add in a line whatever you would have typed in a terminal to execute the script!
e.g.:

#!bin/bash
./myscript.sh &

if the script to be executed is not in same directory, just use the complete path of the script.
e.g.:`/home/user/script-directory/./myscript.sh &

Comments

11

The top answer suggests adding #!/bin/bash line to the first line of the sub-script being called. But even if you add the shebang, it is much faster* to run a script in a sub-shell and capture the output:

$(source SCRIPT_NAME)

This works when you want to keep running the same interpreter (e.g. from bash to another bash script) and ensures that the shebang line of the sub-script is not executed.

For example:

#!/bin/bash
SUB_SCRIPT=$(mktemp)
echo "#!/bin/bash" > $SUB_SCRIPT
echo 'echo $1' >> $SUB_SCRIPT
chmod +x $SUB_SCRIPT
if [[ $1 == "--source" ]]; then
  for X in $(seq 100); do
    MODE=$(source $SUB_SCRIPT "source on")
  done
else
  for X in $(seq 100); do
    MODE=$($SUB_SCRIPT "source off")
  done
fi
echo $MODE
rm $SUB_SCRIPT

Output:

~ ❯❯❯ time ./test.sh
source off
./test.sh  0.15s user 0.16s system 87% cpu 0.360 total

~ ❯❯❯ time ./test.sh --source
source on
./test.sh --source  0.05s user 0.06s system 95% cpu 0.114 total

* For example when virus or security tools are running on a device it might take an extra 100ms to exec a new process.

Comments

11

This was what worked for me, this is the content of the main sh script that executes the other one.

#!/bin/bash 
source /path/to/other.sh

Comments

5
pathToShell="/home/praveen/"   
chmod a+x $pathToShell"myShell.sh"
sh $pathToShell"myShell.sh"

Comments

5
 #!/bin/bash

 # Here you define the absolute path of your script

 scriptPath="/home/user/pathScript/"

 # Name of your script

 scriptName="myscript.sh"

 # Here you execute your script

 $scriptPath/$scriptName

 # Result of script execution

 result=$?

1 Comment

incorrect for folder scriptPath or file name scriptName with spaces
5
chmod a+x /path/to/file-to-be-executed

That was the only thing I needed. Once the script to be executed is made executable like this, you (at least in my case) don't need any other extra operation like sh or ./ while you are calling the script.

Thanks to the comment of @Nathan Lilienthal

Comments

4

Assume the new file is "/home/satya/app/app_specific_env" and the file contents are as follows

#!bin/bash

export FAV_NUMBER="2211"

Append this file reference to ~/.bashrc file

source /home/satya/app/app_specific_env

When ever you restart the machine or relogin, try echo $FAV_NUMBER in the terminal. It will output the value.

Just in case if you want to see the effect right away, source ~/.bashrc in the command line.

Comments

3

There are some problems to import functions from other file.
First: You needn't to do this file executable. Better not to do so! just add

. file

to import all functions. And all of them will be as if they are defined in your file.
Second: You may be define the function with the same name. It will be overwritten. It's bad. You may declare like that

declare -f new_function_name=old_function_name 

and only after that do import. So you may call old function by new name.
Third: You may import only full list of functions defined in file. If some not needed you may unset them. But if you rewrite your functions after unset they will be lost. But if you set reference to it as described above you may restore after unset with the same name.
Finally In common procedure of import is dangerous and not so simple. Be careful! You may write script to do this more easier and safe. If you use only part of functions(not all) better split them in different files. Unfortunately this technique not made well in bash. In python for example and some other script languages it's easy and safe. Possible to make partial import only needed functions with its own names. We all want that in next bush versions will be done the same functionality. But now We must write many additional cod so as to do what you want.

1 Comment

(Welcome to SO!) As user Praveen was last seen in 2011, it is bound to be difficult to sort out whether the question was how to make the shell executing a.sh execute b.sh (and continue executing a.sh if not commanded otherwise), or to literally call b.sh. (My spelling checker doesn't catch bush versions.) (Do you have someone to turn to to help you with English grammar? (Sometimes wish I had.))
3

Use backticks.

$ ./script-that-consumes-argument.sh `sh script-that-produces-argument.sh`

Then fetch the output of the producer script as an argument on the consumer script.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.