what console command ./ means?

I saw many times console commands like

./redis-server

or

./mongo

what exactly ./ means?


Solution 1:

. is the current directory. So the command is telling the shell to look for the executable in the current directory.

Do not confuse with . foo, which is a completely different command.

Solution 2:

Wen you run a command without any prefix then Unix systems look up the command within PATH. For example if you type ls then Unix will walk all paths listed in PATH to find the ls binary.

For example let's assume your PATH is set to /bin:/usr/bin:/usr/local/bin then just typing ls will make your shell find the command at /bin/ls and execute it.

Unix systems shall evaluate the paths in the order they are listed in PATH. So if you have multiple ls installed it will execute the one found first ignoring the others. So in the example above you might have another ls installed at /usr/local/bin/ls which is never used if you just type ls. If you want to execute /usr/local/bin/ls instead then you can either modify PATH or use the absolute path typing /usr/local/bin/ls.

Now it comes to your ./ prefix. The . is simply referring the current folder. So if you prefix a command with ./ your shell looks for the command in the current folder. In fact

./command

is identical to

`pwd`/command

or (on BASH)

${PWD}/command

As already mentioned on Windows command line you might be used to just enter command if you want to execute command.exe from the current folder. This is because Windows implicitly first looks in the current working folder for the binary before searching the path.

Unfortunately this is quite insecure. Let's imagine I would like to steal user information which I don't have access to as a normal user. I will just place a very simple script into my home directory called 'ls' with the following content:

#!/bin/bash
cp /etc/shadow /home/my-user > /dev/null 2>&1
chown my-user /home/my-user/shadow > /dev/null 2>&1
/bin/ls $*

Then make it executable.

Then I call up my system administrator and tell him some story about some pretty strange filenames in my home directory. Very likely the admin logs in on the shell (hopefully as root) cd's into my directory and executes ls. What would happen is that instead of /bin/ls the system administrator would execute my ls script which just places a copy of /etc/shadow into my home folder. Well, the administrator would probably wonder why this ls will not list the file names. So the script just executes the "real" /bin/ls command on the last line.

So in order to prevent such issues most modern Unix systems do not include the current directory (.) in the search path. Basically if a command is executed without specifying the complete path the shell will just execute binaries within the path which typically includes trusted paths only (non user-writable). When you see ./mongo in a documentation this just means that you have to make sure that mongo from the correct folder is executed, and not some mongo binary somewhere in the path.

If you're often executing binaries from the current path you might simply add "." to the PATH list manually:

export PATH=".:$PATH"

Starting from now the shell will always look for binaries in the current directory first. As written above this is highly dangerous as you would have to check the current working directory for binaries every time you execute a command - even before executing it. Unfortunately to check the current directory for binaries usually you would use 'ls` which could already execute a binary you would not expect.

I personally often use the following in my $HOME/.profile:

export PATH="~/bin:$PATH"

This allows me to put some scripts in my $HOME/bin folder and run them without having to specify the full path. But remember that $HOME/bin is a trusted path for me as well.

Another small note. Each directory (even empty ones) contain two hard links. Check ls -a output:

.
..

The . entry refers to the current directory while the .. entry is hard-linked to the parent directory. This is enabling relative paths. Of course it also allows recursive definitions such as ././././././command to execute command as . always refers to the same directory. You can also execute something like /bin/../bin/./././../bin/ls which is entirely valid.

I hope this clarifies a bit what the . and .. entries are about.