Why do you need ./ (dot-slash) before executable or script name to run it in bash?

Viewed 121089

When running scripts in bash, I have to write ./ in the beginning:

$ ./manage.py syncdb

If I don't, I get an error message:

$ manage.py syncdb
-bash: manage.py: command not found

What is the reason for this? I thought . is an alias for current folder, and therefore these two calls should be equivalent.

I also don't understand why I don't need ./ when running applications, such as:

user:/home/user$ cd /usr/bin
user:/usr/bin$ git

(which runs without ./)

9 Answers

This question already has some awesome answers, but I wanted to add that, if your executable is on the PATH, and you get very different outputs when you run

./executable

to the ones you get if you run

executable

(let's say you run into error messages with the one and not the other), then the problem could be that you have two different versions of the executable on your machine: one on the path, and the other not.

Check this by running

which executable

and

whereis executable

It fixed my issues...I had three versions of the executable, only one of which was compiled correctly for the environment.

Rationale for the / POSIX PATH rule

The rule was mentioned at: Why do you need ./ (dot-slash) before executable or script name to run it in bash? but I would like to explain why I think that is a good design in more detail.

First, an explicit full version of the rule is:

  • if the path contains / (e.g. ./someprog, /bin/someprog, ./bin/someprog): CWD is used and PATH isn't
  • if the path does not contain / (e.g. someprog): PATH is used and CWD isn't

Now, suppose that running:

someprog

would search:

  • relative to CWD first
  • relative to PATH after

Then, if you wanted to run /bin/someprog from your distro, and you did:

someprog

it would sometimes work, but others it would fail, because you might be in a directory that contains another unrelated someprog program.

Therefore, you would soon learn that this is not reliable, and you would end up always using absolute paths when you want to use PATH, therefore defeating the purpose of PATH.

This is also why having relative paths in your PATH is a really bad idea. I'm looking at you, node_modules/bin.

Conversely, suppose that running:

./someprog

Would search:

  • relative to PATH first
  • relative to CWD after

Then, if you just downloaded a script someprog from a git repository and wanted to run it from CWD, you would never be sure that this is the actual program that would run, because maybe your distro has a:

/bin/someprog

which is in you PATH from some package you installed after drinking too much after Christmas last year.

Therefore, once again, you would be forced to always run local scripts relative to CWD with full paths to know what you are running:

"$(pwd)/someprog"

which would be extremely annoying as well.

Another rule that you might be tempted to come up with would be:

relative paths use only PATH, absolute paths only CWD

but once again this forces users to always use absolute paths for non-PATH scripts with "$(pwd)/someprog".

The / path search rule offers a simple to remember solution to the about problem:

  • slash: don't use PATH
  • no slash: only use PATH

which makes it super easy to always know what you are running, by relying on the fact that files in the current directory can be expressed either as ./somefile or somefile, and so it gives special meaning to one of them.

Sometimes, is slightly annoying that you cannot search for some/prog relative to PATH, but I don't see a saner solution to this.

All has great answer on the question, and yes this is only applicable when running it on the current directory not unless you include the absolute path. See my samples below.

Also, the (dot-slash) made sense to me when I've the command on the child folder tmp2 (/tmp/tmp2) and it uses (double dot-slash).

SAMPLE:

[fifiip-172-31-17-12 tmp]$ ./StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ /tmp/StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ mkdir tmp2

[fifi@ip-172-31-17-12 tmp]$ cd tmp2/

[fifi@ip-172-31-17-12 tmp2]$ ../StackO.sh

Hello Stack Overflow
Related