117

Why do we use ./filename to execute a file in linux?

Why not just enter it like other commands gcc, ls etc...

Ciro Santilli OurBigBook.com
  • 18,092
  • 4
  • 117
  • 102
Renjith G
  • 5,888
  • Wouldn't the first line be better written as "Why do we use ./command_name to execute a command in linux?" –  Jul 26 '13 at 06:18
  • user15760, No, because we like questions to be discoverable in search engines and not all who have this question are natural born 'nixsters (: – Bahram Ardalan Dec 19 '20 at 20:28

6 Answers6

129

The literal answer is as others have given: because the current directory isn't in your $PATH.

But why? In short, it's for security. If you're looking in someone else's home directory (or /tmp), and type just gcc or ls, you want to know you're running the real one, not a malicious version your prankster friend has written which erases all your files. Another example would be test or [, which might override those commands in shell scripts, if your shell doesn't have those as built-ins.

Having . as the last entry in your path is a bit safer, but there are other attacks which make use of that. An easy one is to exploit common typos, like sl or ls-l. Or, find a common command that happens to be not installed on this system — vim, for example, since sysadmins are of above-average likelyhood to type that.

Does this sound too theoretical? It largely is, but it definitely can happen in reality, especially on multi-user systems. In fact, here is an example from this site where an administrator switched to a users' home directory and found ps to be masked by an executable of that name.

mattdm
  • 40,245
101

In Linux, UNIX and related operating systems, . denotes the current directory. Since you want to run a file in your current directory and that directory is not in your $PATH, you need the ./ bit to tell the shell where the executable is. So, ./foo means run the executable called foo that is in this directory.

You can use type or which to get the full path of any commands found in your $PATH.

terdon
  • 242,166
badp
  • 2,977
  • 8
    It is very common to execute programs in the current directory. Why doesn't the shell search in there as well? It first searches in ., then in $PATH. – Michael Jul 09 '13 at 22:14
  • 2
    there are also aliases that can get in the way, not just $PATH . – user2485710 Oct 14 '14 at 21:35
  • 29
    @Michael security and sanity: If it searched in . first then it would be a security issue, you or someone else could replace ls for example (a simple virus/trojen: make a zip file with an executable named ls in it, as someone is searching through, they run this executable, that …) . If it searched in . last then you can spend a long time going crazy not knowing why your program is not working (e.g. you make a program called test, instead of running your program it runs the systems test program. Which produces no output). – ctrl-alt-delor Mar 14 '15 at 18:24
  • It also ensures that if the application or script appears multiple times in your path, that you are executing the version that you intend to run (the one right here in your "." directory). – Jim2B Jul 07 '15 at 18:43
  • You can execute export PATH="$PATH:." to execute command in current directory if not found elsewhere in PATH, you can add this in your .bashrc file – jcubic Apr 23 '17 at 10:01
  • 3
    @jcubic that's a bad idea. See the comment above. In the past DOS searches in the current directory and that behavior was carried onto Windows cmd which introduces a lot of security issues. MS fixed that in PowerShell and now you must use .\ to run the program in the current directory – phuclv Mar 15 '20 at 09:41
  • 2
    @ctrl-alt-delor: When I was at university in the late 80's, this was a common (prohibited) tactic. Writing an "ls" program and leaving it in your home folder in case someone else came snooping. The program was called a "get shell" IIRC. It would try to get the credentials of the user running the command - and then maybe print a fake directory listing to leave them unaware. – Nick Westgate Aug 12 '20 at 05:30
45

If you mean, why do you need ./ at the start - that's because (unlike in Windows), the current directory isn't part of your path by default. If you run:

$ ls

your shell looks for ls in the directories in your PATH environment variable (echo $PATH to see it), and runs the first executable called ls that it finds. If you type:

$ a.out

the shell will do likewise - but it probably won't find an executable called a.out. You need to tell the shell where a.out is - it it's in the current directory (.) then the path is ./a.out.

If you're asking why it's called "a.out", that's just the default output file name for gcc. You can change it with the -o command line arg. For example:

$ gcc test.c -o test
$ ./test
  • Thanks.My doubt is why do you need ./ at the start.... I got the use of "." (to poit the current directory) but why "/" after that? – Renjith G Nov 30 '10 at 08:35
  • 8
    / is the path separator in Linux, so you use it to separate the directory (.) from the filename (a.out). Without it you have .a.out which is a valid filename in its own right. (Try touch .a.out; ls -lA to see this.) – Simon Whitaker Nov 30 '10 at 08:37
  • 5
    that is how you specify the path in Unix, <dir>/<file> so you are basically saying execute a file in the current directory, which is indicated by ./test – Rohan Monga Nov 30 '10 at 08:37
  • Red Hat Linux release 9 (Shrike) Kernel 2.4.20-8 on an i686 [renjithg@cvsserver renjithg]$ touch .a.out;ls -lA total 3 -rw-rw-r-- 1 renjithg renjithg 0 Nov 30 13:46 .a.out -rwxrwxr-x 1 renjithg renjithg 11669 Nov 30 13:46 a.out -rw-rw-r-- 1 renjithg renjithg 218 Aug 24 2009 aray.c [renjithg@cvsserver renjithg]$ – Renjith G Nov 30 '10 at 08:48
  • 4
    Red Hat Linux 9? Time to upgrade! – mattdm Feb 17 '11 at 01:53
  • 1
    On Windows 10 PowerShell is the default shell now, and it also requires ./ to run an executable in the current path – Carl Walsh Aug 06 '19 at 02:59
6

You can try to add :. to your $PATH variable.

Try ALT+F2 and type: gksudo gedit /etc/environment if running Linux/GTK (this is what you have if using Ubuntu).

HOWEVER, I strongly advise you NOT to do that. It's bad bad bad and bad.

You know, that kind of things work like this since 1970. There is a reason why the current directory isn't included in the $PATH.

. is the current directory

.something would be a hidden file (Type "ALT+" to make them appear in Nautilus, or try "ls -la".

./someProgram.sh is what you type to RUN an executable someProgram.sh in the current directory.

.somethingElse would mean that you have a hidden executable in the current directory, which is a bad idea.

tiktak
  • 492
  • 3
  • 7
5

The more complete rule is actually: if any slash / is in the path, don't search PATH

Before we go into the rationale, you should first know about this fact: running either of:

bin/someprog

or:

/bin/someprog

or:

cd bin
./myexec

execute bin/someprog without searching the PATH variable for the exact same reason: all of bin/someprog, /bin/someprog and ./someprog have a slash / in them.

someprog alone does not have a slash /, and therefore searches only in PATH.

POSIX 7 specifies this rule at: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01

PATH

[...] If the pathname being sought contains a <slash>, the search through the path prefixes shall not be performed.

Rationale for the / POSIX PATH rule

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.

Ciro Santilli OurBigBook.com
  • 18,092
  • 4
  • 117
  • 102
-3

I have been reading Linux manuals since 1999, and none of the security arguments make any sense. The real reason is that Linux allows any file to be executed, of any extension. The whole reason you have extensions is to avoid clicking on any file, or calling any file, on accident.

In Windows, you have exe, bats, which any user knows not to click on, unless they put them there themselves or wrote the program. Problem solved. However, there is an idiot warning now days that you are running an exe. A good application firewall allows rules for running new untrusted applications, as well as which folders it can write to.

I don't know where most folks get their ideas of security.

  1. I need to see the extension.
  2. run an application firewall (I am not talking an internet or network firewall), which is way better than permissions, or at least needs to be layers on top.
serenesat
  • 1,326