0

I have a shell script that doesn't execute with ./script.sh but it requires . ./script.sh to execute.

What is the difference between ./ and . ./? I am using the MSYS2 environment on Windows. Please note the space between the dots. I know what ../, does and that doesn't solve the issue, as I am in the same directory as my executable.

Here's the output:

terminal output

JC2020
  • 9
  • Are you sure there is a space between the two dots? The current answer explains why ../ works; . ./ wouldn't work. – Jos Nov 27 '20 at 09:06
  • Yes there is a space. I don't have enough reputation to post an image. – JC2020 Nov 27 '20 at 09:08
  • 3
    Does this answer your question? In a bash script what does a dot followed by a space and then a path mean? I assume your default shell is bash. – Kulfy Nov 27 '20 at 09:17
  • 1
    Another reason that ./script.sh might not run is if you haven't turned on the "execute" bit on. i.e., you would have to do a chmod u+x script.sh first. It depends what error did you get when you tried ./script.sh. Did you get a "permission denied"? – Ray Nov 27 '20 at 09:53
  • @Kulfy Actually, that alone may not satisfy the OP's question. We don't know what error was from ./script.sh. I am guessing the file also doesn't have execute permissions, which is why it cannot be run directly. – Ray Nov 27 '20 at 09:58
  • @Ray I have posted an output of my command window on the question. I have another script there called install.sh, and that runs perfectly fine with ./install.sh. However export.sh requires '. ./export.sh' – JC2020 Nov 27 '20 at 10:04
  • The message you posted is produced specifically by export.sh, it isn't any system error. This indicates that export.sh has been specially written to be sourced, and not executed, and is checking this. Probably because - as the name suggests - it exports some variables into the environment, which would have no result if the script were executed, because it would then have it's own temporary environment. Sourcing causes the script run in current shell context (and current environment) without starting a new temporary shell. – raj Nov 27 '20 at 12:54
  • 1
    @JC2020 Sorry, I completely forgot (and misread) the part about you using MSYS2... I'm not sure why you're asking on askubuntu.com . It's not really relevant. Personally, I don't consider it Linux and certainly not Ubuntu. Latest versions of Windows allows you to install Ubuntu inside. Perhaps you can consider that instead? Using Linux properly would probably be better... – Ray Nov 28 '20 at 14:52

2 Answers2

7

. is a source operator in Bash and multiple other POSIX shells:

$ help .
.: . filename [arguments]
    Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell.  The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.

Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.

It's always safer to do . ./script instead of . script because . searches PATH by default and you can run into name collisions:

$ echo echo hi > script
$ . script
bash: .: /usr/bin/script: cannot execute binary file
$ . ./script
hi

And because some shells do not search current directory be default:

$ mv script script-to-be-sourced
$ dash
$ . script-to-be-sourced
dash: 1: .: script-to-be-sourced: not found
2

The two are completely different, and can not be compared.

./ means the current directory.

. ./ means nothing like as it is, running will print the following error:

-bash: .: ./: is a directory

However, it needs to be broken down in two:

  • The . command
  • The ./ parameter

The . command is a shell built-in which is a synonym to the source command. It takes a file and not a directory as a parameter which is why you would get the error above.

A very command example that you might have seen is the following command:

$ . ~/.bashrc

And that is exactly synonym to

$ source ~/.bashrc

You can find their manual by running

man bash-builtins
        .  filename [arguments]
       source filename [arguments]
              Read and execute commands from filename in the current shell environment and return
              the exit status of the last command executed from filename.  If filename  does  not
              contain  a  slash,  filenames  in  PATH  are  used to find the directory containing
              filename.  The file searched for in PATH need not be executable.  When bash is  not
              in  posix  mode, the current directory is searched if no file is found in PATH.  If
              the sourcepath option to the shopt builtin command is turned off, the PATH  is  not
              searched.   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 status of the last command exited within the script (0 if no
              commands are executed), and false if filename is not found or cannot be read.

Lorenz Keel
  • 8,905
Dan
  • 13,119
  • . ./ gives an error, but . ./script.sh (that's what OP asked about) does not - it sources the script script.sh – raj Nov 27 '20 at 09:49
  • @raj I think the OP said ./script.sh gives an error, but not . ./script.sh? – Ray Nov 27 '20 at 09:57
  • Yes, and he asked about the difference between those two. He didn't try to run . ./ – raj Nov 27 '20 at 12:49