Faisal M
Faisal M

Reputation: 21

why does "source ~/.profile" keep adding to my $PATH?

This is not a problem affecting me in any way, but just for curiosity...

I have added export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin to my ~/.profile to include a new directory into my bash search.

Then, I ran $ source ~/.profile to reload may shell and I checked my path using $ echo $PATH

The question is:
- why every time I ran source ~/.profile, it appends the same information again,
- how can I clear it?

What I have tried:
- Tried running it multiple times and it keeps adding the same
- Tried to figure out what does the source command does but could not find where it is which source

Upvotes: 1

Views: 2695

Answers (2)

fedterzi
fedterzi

Reputation: 1164

source executes the content of the file passed as argument in the current shell.

It appends the same information again because export is appending a string to PATH, without checking anything (it is not checking if the substring that you want to append is already in the variable).

To avoid appending to PATH every time, you should save the values of your PATH without referring to itself, e.g.:

export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/local/go/bin:$GOPATH/bin

Edit: To check if the directory is already in PATH:

if [[ ":$PATH:" != *":/usr/local/go/bin:$GOPATH/bin:"* ]]; then
    export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
fi

Upvotes: -1

Arkadiusz Drabczyk
Arkadiusz Drabczyk

Reputation: 12548

First question:

why every time I ran source ~/.profile, it appends the same information again

Simply, source <FILE> does not reload your shell. It only executes all commands saved in <FILE> as if they were typed directly by you in the terminal.

Second question:

how can I clear it?

To reload shell open a new terminal window/tab. Doing just bash or exec bash won't work because a new process will inherit its parent environment.

Third question:

Tried to figure out what does the source command does but could not find where it is which source

As I explained once here https://unix.stackexchange.com/a/202326/72304:

All commands that can be run in Bash without typing an explicit path to it such as ./command can be divided into two parts: Bash shell builtins and external commands. Bash shell builtins come installed with Bash and are part of it while external commands are not part of Bash. This is important because Bash shell builtins are documented inside man bash and their documentation can be also invoked with help command while external commands are usually documented in their own manpages or take some king of -h, --help flag. To check whether a command is a Bash shell builtin or an external command:

$  type local 
 local is a shell builtin

It will display how command would be interpreted if used as a command name (from help type). Here we can see that local is a shell builtin. Let's see another example:

$ type vim 
vim is /usr/bin/vim

In your case:

$ type source
source is a shell builtin

Now we know it's not an external command but a shell bultin (this is why which does not find it) so we need to use help to see what it does:

$ help source 
    source: source filename [arguments]
    Execute commands from a file in the current shell.

    Read and execute commands from FILENAME in the current shell.  The
    entries in $PATH are used to find the directory containing FILENAME.
    If any ARGUMENTS are supplied, they become the positional parameters
    when FILENAME is executed.

    Exit Status:
    Returns the status of the last command executed in FILENAME; fails if
    FILENAME cannot be read.

Upvotes: 3

Related Questions