What happens when I execute a unix shell script using a '.' command? - bash

For example, when I say . .bashrc on my Linux command prompt, is there a corresponding binary/script that gets executed in place of the first dot? If the dot itself is a command, where is its location?

The . operator is shorthand for the source Bash builtin (as pointed out by John Kugelman below). Typing
help .
or
help source
at the Bash prompt will give you some information. For more on how source works, see http://www.ss64.com/bash/period.html.

Additionally I want to point out that you don't "execute" anything with it (in terms of fork/exec), which is very important (and probably the only reason '.' exists).

Related

What does . mean in bash? (As in ". script.sh")

I am used to running shell scripts with for example
source script.sh
I was surprised to learn recently that this also works
. script.sh
The single dot of course normally indicates the current directory so I am now confused. Can anyone explain this use of .?
Taken from IBM docs: ".(dot) runs a shell script in the current environment and then returns. Normally, the shell runs a command file in a child shell so that changes to the environment by such commands as cd, set, and trap are local to the command file. The . (dot) command circumvents this feature.
If there are slashes in the file name, . (dot) looks for the named file. If there are no slashes . (dot) searches for file in the directories specified in the PATH variable. This may surprise some people when they use dot to run a file in the working directory, but their search rules are not set up to look at the working directory. As a result, the shell does not find the shell file."
. (dot) and source mean the same thing in the bash language.
In fact the (dot) form is the standard form according to the POSIX Shell Specification. The source form is a bash extension, but not a bash invention. (The venerable Berkley C-shell (csh) used to use source rather than ..)
According to the POSIX Shell specification, source is a command name whose meaning is unspecified; see https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html

Change directory through bash script without messing up $PATH

Yes, I know that I can run
. my_cd_script.sh
to change my directory directly. However, once I do that, my $PATH is messed up. For instance, when I type ls, the shell will return Command not found.
Anyone encountered this?
I named a variable "path" without a second thought, although I would've expected shell to be case sensitive. – user1836155
If you're running into variable names not seeming to be case-sensitive, then I suspect you're not actually using bash. Maybe csh instead, or some other variant in the csh family... – twalberg
I used the "#!/bin/bash" header though – user1836155
The header means nothing when you source a file with . myscript - it's just a comment in that case. – twalberg

How can I store and execute the command "export PATH=$PREFIX/bin" from a script?

I would like to write a script that has several commands of the kind
> export PATH=$PREFIX/bin
Where
> $PREFIX = /home/usr
or something else. Instead of typing it into the the Shell (/bin/bash) I would run the script to execute the commands.
Tried it with sh and then with a .py script having the line,
> commands.getstatusoutput('export PATH=$PREFIX/bin')
but these result into the error "bad variable name".
Would be thankful for some ideas!
If you need to adjust PATH (or any other environment variable) via a script after your .profile and equivalents have been run, you need to 'dot' or 'source' the file containing the script:
. file_setting_path
source file_setting_path
The . notation applies to all Bourne shell derivatives, and is standardized by POSIX. The source notation is used in C shell and has infected Bash completely unnecessarily.
Note that the file (file_setting_path) can be specified as a pathname, or if it lives in a directory listed on $PATH, it will be found. It only needs to be readable; it does not have to be executable.
The way the dot command works is that it reads the named file as part of the current shell environment, rather than executing it in a sub-shell like a normal script would be executed. Normally, the sub-shell sets its environment happily, but that doesn't affect the calling script.
The bad variable name is probably just a complaint that $PREFIX is undefined.
Usually a setting of PATH would look something like
export PATH=$PATH:/new/path/to/programs
so that you retain the old PATH but add something onto the end.
You are best off putting such things in your .bashrc so that they get run every time you log in.

Source a script with a different shell type

Let's say a script is called with /bin/sh. Is it possible to source another script from that script and to have it be interpreted with #!/bin/bash?
It would appear that the #!/bin/bash doesn't do anything...
And by source, at this point I am meaning the functionality of manipulating the parent environment.
No. The whole point of sourcing a script is that the script is interpreted by the shell doing the sourcing. If, as is often the case, /bin/sh is bash, then you will get the desired behavior. Otherwise, you are out of luck.
Try the source command, or dot operator. You might also try the env command. Note, make sure you export if you're using source (or dot).

What does ". ./some/script.sh" mean in detail?

There are two options to run a shell script:
$ ./some/script.sh
$ . ./some/script.sh
As far as I unterstand, the first one starts a new shell environment based on the given shebang line withing the script. While the second one executes the statements within the same shell environemnt.
Are there more differences ?
Where can I find more documentation about the second one ?
Is . a real command ? I can not find a manpage to it.
Are there more differences ?
The gist of the matter is that using . the script is executed line by line in the same process. Otherwise a new process is forked. And a separate process has no way of changing the parent, for example it can't change environment variables such as the current directory.
Where can I find more documentation about the second one ?
[cnicutar#fresh ~]$ help source
source: source filename [arguments]
...
Is . a real command
[cnicutar#fresh ~]$ type .
. is a shell builtin
In case it isn't obvious already, . and source are identical*.
As rush commented, source isn't specified by POSIX so you should probably use . in code intended to be portable. The dot is specified in chapter 2.
. is a Bourne Shell command for reading a file and executing the commands in the file, your analysis is essentially correct. bash and other shells add source as an alias for ..
See the manual for bash builtins, and see . at the top of the manual for Bourne sh builtins.
Read and execute commands from the filename argument in the current shell context. If filename does not contain a slash, the PATH variable is used to find filename. When Bash is not in posix mode, the current directory is searched if filename is not found in $PATH. If any arguments are supplied, they become the positional parameters when filename is executed. Otherwise the positional parameters are unchanged. The return status is the exit status of the last command executed, or zero if no commands are executed. If filename is not found, or cannot be read, the return status is non-zero. This builtin is equivalent to source.
it is used to source an environment. such as the .profile.

Resources