The minus sign is the way the system tells the shell that it's invoked as a login shell and it should source ~/.profile
(for Bourne-compatible shells). This is true on Linux, OSX and every other unix. A script would not be run in a login shell. For a script, $0
is the name of the script file (with or without the full path).
ADDED: The man page does explain (almost all) the different cases:
“If bash is invoked with a file of commands, $0 is set to the name of that file.” This covers scripts executed with bash myscript
, as well as the indirect case where the script is executed directly and starts with #!/bin/bash
.
“If bash is started with the -c option, then $0 is set to the first argument after the string to be executed, if one is present.” With -c
, $0
is set to whatever the caller explicitly indicates.
“Otherwise, it is set to the file name used to invoke bash, as given by argument zero.” A login shell falls into this case: the shell is invoked with no arguments other than argument zero, so $0
is set to argument zero. It is login
, su
, or whatever program handled the login that chooses the arguments that it passed to the shell, and prepends a -
to argument zero to tell the shell that it's a login shell.
Perhaps some explanation of argument zero is in order. When a program is executed, ultimately, an execve
system call takes place. That system call takes three arguments:
a file name, which must designate an existing, executable file. The kernel loads this file and transfers execution to it.
an array of strings, called the arguments. Element zero in this array is by convention the same file name as above, or the just the file name without the full path if the location of the executable was determined by searching the $PATH
environment variable. There are exceptions to this convention, such as login shells.
another array of strings, called the environment.
When you call a program from the shell by typing myprogram foo bar
, the arguments to execve
are:
1. /usr/bin/myprogram
(assuming this is where the shell found myprogram
)
2. myprogram
, foo
, bar
3. for each exported shell variable, the variable name followed by an equal sign and the value.
There is no general way to find the name of the executable file that was passed to execve
from the running program. Under Linux, it's usually available as /proc/$$/exe
where $$
is the process ID. Every unix makes it available to ps
but the inner workings of ps
differ widely. The executable may be deleted or renamed while the program is running; in this case ps
might report obsolete information or no information.
The most common problem caused by misuse of shell startup files is that if you define environment variables in .bashrc
as opposed to .profile
, they are not defined in applications that are not launched from a shell in a terminal but rather from a GUI menu.
Defining environment variables from .bashrc
is generally not a good idea, but that's primarily because it's generally useless as the variables should already have been set at login time. It can cause a problem in practice if you (or an application) have deliberately changed the value of a variable (e.g. PATH
) in a program and you launch a shell from that program and expect the setting to have remained the same.
You can avoid the problem of environment variables being reset by defining a “sentinel” value, and not defining anything if the sentinel value is set:
if [ -z "$JMLANE_PROFILE_READ" ]; then
export ...
export JMLANE_PROFILE_READ=1
fi
Another problem caused by terminals starting login shells is that there are things that should only be done once when you log in, for example starting a password agent (e.g. ssh-agent
), or initiating a session (e.g. running startx
in certain circumstances). The sentinel variable avoids these issues.
A shell inside a terminal is always interactive. As long as you source .bashrc
from .bash_profile
when the shell is interactive, you don't need to worry about the terminal starting a login shell.
An additional wart of bash's startup file handling is that .bashrc
is read by non-interactive shells invoked by rshd or sshd. For example, when you do rsync somefile host.example.com:
, if your login shell on host.example.com
is bash, you can use .bashrc
there to set the path to include rsync
. You can tell you're in this situation because .bashrc
is read from a non-interactive shell.
## .bashrc
if [[ $- != *i* ]]; then
# either .bashrc was executed explicitly or this is a noninteractive rsh/ssh session
fi
Best Answer
To turn on colour output from the
ls
command without having to create an alias tols
or download any additional software, add the following to your~/.bash_profile
:If you don't like those colours you can use this ls color generator to customize that color list to your liking.
You'll need to do:
After making any changes for them to take effect in your existing shell.