Why do I need ./ to run an application? [duplicate]
While executing a C program, a.out
, using the Ubuntu terminal, why do I always need to type ./
before a.out
, instead of just writing a.out
? Is there solution for this?
Solution 1:
When you type the name of a program such as a.out
the system looks for the file in your PATH. On my system, PATH is set to
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
Yours is probably similar. To check, enter echo $PATH
in a terminal.
The system looks through these directories in the order given and if it can't find the program produces a command not found
error.
Prepending the command with ./
effectively says "forget about the PATH, I want you to look only in the current directory".
Similarly you can tell the system to look in only another specific location by prepending the command with a relative or absolute path such as:
../
means in the parent directory eg ../hello
look for hello in the parent directory.
./Debug/hello
: "look for hello
in the Debug subdirectory of my current directory."
or /bin/ls
: "look for ls
in the directory /bin
"
By default, the current directory is not in the path because it's considered a security risk. See Why is . not in the path by default? on Superuser for why.
It's possible to add the current directory to your PATH, but for the reasons given in the linked question, I would not recommend it.
Solution 2:
The reason for this is simple.
Suppose you have a command with the same name as an application in the current directory. Then running the command in the shell would invoke your app instead of the built-in command. This would be a security concern if nothing else.
By requiring ./
to be used in front, the shell knows that you want to execute the application with the given name and not a built-in command with that name.
Solution 3:
./
executes files that are not in your $PATH
, rather it executes the file in the current directory (or another via ./home/stefano/script.sh
). Now, PATH is an environment variable that contains all of the places where bash can look for executable programs, without having the full (absolute) path to them.
This seperation is needed to avoid running the wrong file. I.e. if you have a file called ls
in your home directory, it not being in your PATH will prevent bash from confusing it with the real ls
. The PATH variable also defines the search order:
- When you run a command, or a program tries to make an
exec
syscall (a special method of the Kernel, how programs are started), the system looks for the file by going through each of the directories in your PATH. Once the program has been found, even if it's in multiple directories, the search is interrupted and the first one found is run.
To run a file, you will need to set the executable bit in the permissions:
-
Since you're already on the command line, you can just type
chmod +x finename
. -
Or you can set the permissions by right clicking the file and selecting Properties:
You can now copy the file to any of the directories in PATH, to see which ones are in there - and they're set on a per-user basis - type echo $PATH
.
stefano@3000-G530:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
If you create an executable file, cat
, and move it to /usr/local/sbin
, it is run instead of the proper cat
, which resides in /bin
. You can find out where your files are by using type cat
and whereis cat
.
Solution 4:
Why do you need to type ./
before executing a program?
In the terminal, whenever you type the name of an application, let's say gedit
, the terminal will go look in some (pre-defined) directories that contain applications (the binaries of the applications). The names of these directories are contained in a variable called PATH
. You can see what's in this variable by executing echo $PATH
. See those directories separated by :
? Those are the directories that the terminal will go search in, if you just type gedit
, nautilus
, or a.out
. As you can see, the path of your a.out
program is not there. When you do ./a.out
, you're telling the terminal "look in the current directory, and run a.out
, and don't go look in PATH
.
Solution 1
If you don't want to type ./
every time, you'll need to add a.out
's directory in $PATH
. In the following instructions, I'll assume that the path to a.out
is /path/to/programs/
, but you should change it to your actual path.
-
Simply add the following line to the end of the file
~/.pam_environment
:PATH DEFAULT=${PATH}:/path/to/programs
Source: Persistent environment variables
Log out and log back in. You'll now be able to run
a.out
without./
from any directory.
If you have other programs in other directories, you can just add those to the above line. However, I'd advise to have one directory called "myPrograms" for example, and put all of your programs under it.
Solution 2
Note: change
userName
to your actual Ubuntu username.
What if you have other programs you want to run? And they're all in different folders? Well, a "more organized" solution would be to create a folder called bin
under your Home directory, and add symbolic links (shortcuts) under that folder. Here's how:
-
mkdir /home/userName/bin
- This will create the folder
bin
under your Home directory.
- This will create the folder
-
ln -s /path/to/programs/a.out /home/userName/bin
- This will create a "symbolic link" (basically, a shortcut) of your
a.out
program underbin
.
- This will create a "symbolic link" (basically, a shortcut) of your
Log out and log back in. You'll now be able to run
a.out
without./
from any directory.
Now, whenever you have another program anywhere else, let's say the program b.in
on your Desktop, all you need to do is: ln -s /home/userName/Desktop/b.in /home/userName/bin
, and you'll then be able to run it without ./
as well.
Note: thanks to @Joe's comment, when you do backups, symbolic links have to be handled specially. By default,
rsync
doesn't process them at all, so when you restore, they're not there.