This question already has answers here:
unix command line execute with . (dot) vs. without
(5 answers)
Closed 7 years ago.
In UNIX, when you want to run a shell script located in pwd, you do:
./somescript.sh
But there is also:
. somescript.sh
What does the second command do?
The dot is an alias for the command "source": http://ss64.com/bash/source.html.
The main difference is that the first syntax tries to execute the script by running some interpreter for it (as determined by the hashbang magic header value). For a shell file, the interpreter is usually bash or sh, and so your shell will launch a new shell process as a subprocess and pass the script as a parameter. The script will run isolated in this subprocess. If it for instance sets an environment variable, it will beisolated to the subprocess and disappear as the subprocess exits
Sourcing the file, OTOH, instructs the current shell to read the instructions in said file. In this case changes will modify the current environment. Changed environment variables will be visible after command completion.
Sourcing only works for shell scripts written for the current shell. Execution works for any type of runnable script/program/executable file.
Related
This question already has answers here:
Source files in a bash script
(2 answers)
Can I export a variable to the environment from a Bash script without sourcing it?
(13 answers)
Closed 2 years ago.
Here is what I have:
script_1.sh
echo "HELLO FROM script_1.sh"
./scripts/script_2.sh
echo $MY_VARIABLE
script_2.sh
echo "HELLO FROM script_2.sh"
export MY_VARIABLE="MY_VALUE"
Here is what it logs when I run script_1.sh:
HELLO FROM script_1.sh
HELLO FROM script_2.sh
"" // EMPTY LINE INSTEAD OF "MY_VALUE"
What am I doing wrong?
Variables are exported from a parent to a child, not vice versa. script_2.sh is called in a different shell whose environment doesn't propagate back to the parent shell.
Source the script (using the .) to call it in the same shell. You then don't even need to export the value.
. ./scripts/script_2.sh
environment variables are inherited down the call chain. they are not returned up to the caller.
in other words: a called script might inherit the variables of the caller. but the caller will not get the variables of the called script.
in you simple example the easiest solution is to "source the script"
. ./scripts/script_2.sh
(the dot is the command to source a script)
sourcing is not a new step in the call chain. instead the sourcer and sourcee share the same environment. for more explanation on the difference of executing and sourcing see here: https://superuser.com/questions/176783/what-is-the-difference-between-executing-a-bash-script-vs-sourcing-it/176788#176788
there are other options but they are more complicated and error prone. it seems that you are starting to learn shell scripting. so learn the difference of sourcing and executing and the implication on the environment for now. if you need other options later then come back and ask another question.
This question already has answers here:
how to run python script without typing 'python ...'
(5 answers)
using alias in shell script? [duplicate]
(7 answers)
Can the child process affect parent process' environment?
(3 answers)
Changing a directory of the parent shell [duplicate]
(2 answers)
Closed 3 years ago.
I am working on a class project that requires a makefile and needs to parse input below as an example
make
myapp arg1 arg2 arg3 arg4....
So I create a myapp.py
import sys
program_name = sys.argv[0]
arguments = sys.argv[1:]
count = len(arguments)
for x in sys.argv:
print("Argument: ", x)
I create a Makefile
all:
alias testapp="python3 myapp.py"
Doing this it should allow me to write
$ testapp arg1 arg2 arg3...
If I manually input the alias statement into the terminal it works correctly, but when run in a Makefile,
it doesn't work for me. Any ideas on a workaround for this? thank you in advance
This is not specific to make.
Aliases are only supported in interactive shells by default.
Also, any code run in a subprocess (i.e. any command you run which is not a shell builtin) will be unable to change anything in the parent process (aliases, variables, etc). So you can't change the behavior of your current shell with make, or a script, or any other external command (except if you cause the shell to cooperate, for example by using a shell builtin which evaluates code printed by a subprocess - eval and source are two common ways to make the shell cooperate).
A simple way to accomplish what you want is to make sure myapp.py has a valid shebang as its very first line
#!/usr/bin/env python3
then make the file executable;
chmod +x myapp.py
then create a symlink to it with the name you want to use in a directory which exists on your PATH. Assuming $HOME/bin already exists and is already on your PATH, simply
ln -s $(pwd)/myapp.py $HOME/bin/testapp
in the directory where you have myapp.py.
Aliases have some drawbacks; maybe prefer shell functions where you could have used an alias.
This question already has answers here:
Can I export a variable to the environment from a Bash script without sourcing it?
(13 answers)
Closed 3 years ago.
I have a simple environment setup script that exports some environment variables like so.
#!/bin/sh
export NEWROOT=~/some/directory
echo $NEWROOT
This echos the correct directory, but after its run, when I echo $NEWROOT in the same shell, it returns nothing.
Any idea why the variable isn't setting?
The shell is run in a separate process, and environment variables in a child process do not affect the environment variables in the parent process.
If you want to run the script in the same process, you can use the dot command, like this:
. myscript
A child process can't affect the environment variables of its parent. If you source the script instead, that will evaluate the script in the current environment, leaving NEWROOT.
This question already has an answer here:
Best way to set environment variables in calling shell
(1 answer)
Closed 8 years ago.
I have a script "set_var.sh" written like this
#!/bin/bash
export NAME=release
export ROOT=/Volumes/name/dev/release
but if I run this set_var.sh from terminal, afterward I issue set command to check variables I could not find NAME and ROOT var be set.
I am wondering what is wrong in my case.
it was set in sub-shell.
you need
source set_var.sh
If you simply run set_var.sh, it runs in its own shell which exits, losing the variables that were set.
If you want to change variables in your interactive shell, you can use:
source set_var.sh
or the shorthand,
. set_var.sh
This will execute the lines of the script as if they were typed into your interactive shell.
Note that when you "source" a file this way, it does not require the "shebang" on the first line.
Note also that this is feature exists in Bourne shell as well, but only in the short-form version.
This question already has answers here:
Should I use a Shebang with Bash scripts?
(8 answers)
Closed 8 years ago.
Suppose you have a bash script B, that you are sourcing from another bash script A. B has a bunch of variable and function definitions. A is the main driver script. Do you need the #!/bin/bash line on top of both A and B? What happens if you do and if you don't?
The shebang is only mandatory for those scripts, which shall be executed by the operating system in the same way as binary executables. If you source in another script, then the shebang is ignored.
On the other hand. IF a script is supposed to be sourced, then it is convention to NOT put any shebang at the start.
The shebang is used if you run the script directly as an executable file (for example with the command ./script.sh). In this case it tells the operating system which executable to run.
It's not required and has no effect if you for example write bash ./script.sh or source the script.
You should use shebang in all scripts especially those using any non-sh compatible features.
In Debian for example, default shell is dash (not bash). If you use bash-only feature and don't specify that this script should be interpreted by bash it may fail even on linux. It will fail on Solaris or HP-UX almost for sure.
If your file is to be only sources by other script, then you can omit shebang line but do not set executable permission. Also for such files is good to keep /bin/sh compatibility.
I strongly recommend to read DashAsBinSh.