Environment Variables in Linux. PATH environment variable Path variable in linux

All files in Linux have a specific address in file system, with which we can access them using the file manager or console utilities. It's pretty simple theme, but many beginners have difficulty with this.

In today's short note, we will look at what a Linux file path is, what it can be, how to write it correctly, and much more. If earlier you had difficulties with this, then after reading the article everything will become completely clear.

File paths in Linux

The Linux file system is very different from Windows. We will not consider its structure, this was done earlier. We will focus on working with files.

The most important difference is that the file address does not start from a drive, for example, C:\ or D:\, as it happens in Windows, but from the root, the root system directory to which all others are connected. His address - /. And here it is necessary to tell about addresses. Linux file paths use a forward slash "/" to separate directories in the address, and this is different from what you're used to seeing on Windows - \.

For example, if in windows full the path to the file on the desktop looked like C:\Users\Sergiy\Desktop\ then the path to the file in linux will simply be /home/sergiy/desktop/. With this, everything is simple and clear. But problems continue to arise.

In the operating room Linux system There can be several types of file paths. Let's look at what paths are in linux:

  • Full, absolute linux path from filesystem root- you have already seen this path in the example above, it starts from the root "/" and describes the entire path to the file;
  • relative linux path is the path to the file relative to the current folder, such paths are often confusing.
  • Path relative to the current user's home folder.- path in the file system, but not from the root, but from the folder of the current user.

Now let's take a closer look at how these paths look in linux, and also analyze a few examples to make it completely clear. To demonstrate, we will use the ls utility, which is designed to view the contents of directories.

For example, we have a directory like this in our home folder with four files in it:

This is how the full linux path to one of the files will look like:

ls /home/sergiy/tmp/file1

This is already a relative linux path that starts from home folder, it is denoted by ~/. Note that not ~, but ~/. Then you can already specify subfolders, in our case tmp:

Well, or the path of the file in linux, relative to the current folder:

The first link points to the current folder (.), the second one (..) points to the folder one level up. This opens up even more possibilities for navigating through directories. For example, to refer to a file in the current folder, you can use the construction:

It's useless when viewing the contents of a file. But it is very important when running the program. Since the program will first be searched in the PATH environment, and only then in this folder. And therefore, if you need to run a program that is located in the current folder and it has the same name as the one in the / bin directory, then without an explicit link that the file needs to be searched in the current folder, nothing will work.

Such constructions can be encountered quite often when compiling programs. You can use all these symbols and linux file paths not only in the terminal, but also in any file manager which can be very convenient.

But the Linux terminal provides even more options. You can use simple replacement characters directly in file or directory addresses. For example, you can list all files that start with f:

Or you can even search not only in the tmp folder, but in any subfolder of your home folder:

And all this will work, perhaps it is not always necessary and practical. But in certain situations it can be very helpful. These functions are implemented at the Bash shell level, so you can use them in any command. The shell looks at how many files were found and calls a command for each of them.

conclusions

That's all. Now you know everything you need to not only correctly write the path to linux file, but also perform more complex actions, such as searching for files or navigating directories using the cd command. If you have any questions, ask in the comments!

Related posts:


Environment variables ( environment variable) are used to store common values variables within different scripts and programs. Such variables can be set for a period of time, for example, for the period of operation of a specific terminal shell, or for the period of a user session, or you can set an environment variable at the global level - for the entire system.

Environment variables

$HOME
The variable contains the path to the current user's home directory. $USER
Current username $PATH
List of directories for the shell to search for executable programs. $PWD
The path to the current working directory (or pwd). Example: dir_path=$(pwd) . $SHELL
Default interpreter $RANDOM
Generates a random number 0..32767 each time the variable is accessed. $SECONDS
Time in sec. since the start of the shell. $? The result of the previous command. $HOSTNAME
Computer name $HISTFILE
Path to $IFS interpreter history file
List of separator characters for commands, parameters, array elements (default: space, tab, newline) $PS1
Interpreter prompt string template.

Temporarily setting an environment variable

Setting an environment variable for the session period:

# For a new process env varname=value [command] # For the current shell and all its subprocesses export varname=value [command]

The value of the variable is retained until the system is rebooted.

Setting a constant value

System-level environment variables are set via the /etc/environment file:

ENVIRONMENT="dev"

Setting a user-specific environment variable via ~/.bashrc or ~/.bash_profile:

PATH="$(PATH):/home/user/bin:"

Attention!

The file ~/.bash_profile will be executed when the interpreter is started with the -l switch. When logged in locally, this file is not readable!

You also need to remember that the changes will take effect only after the session is restarted!

Viewing the value of an environment variable

To view the value of an environment variable, use the printenv command:

Printenv<имя_переменной>

#shell, #bash, #environment

export PATH=~/opt/bin:$PATH

Export PATH=$PATH:~/opt/bin

9 Solutions collect form web for “How to add path to PATH correctly?”

Simple things

PATH=$PATH:~/opt/bin PATH=~/opt/bin:$PATH

depending on whether you want to add ~/opt/bin at the end (to search all other directories if there is a program with the same name in multiple directories) or at the beginning (to search before all other directories).

You can add multiple entries at the same time. PATH=$PATH:~/opt/bin:~/opt/node/bin or changes in collation just fine.

You don't need to export if the variable is already in the environment: any change to the value of a variable is reflected in the environment PATH is almost always in the environment; all unix systems install it very early (usually in the very first process, in fact).

If your PATH is built in different components, you may end up with duplicate entries. See How to add source directory path to be discovered by Unix, which command? and remove duplicate $PATH entries with awk command to avoid adding duplicates or removing them.

Where to put

Note that ~/.bash_rc is not readable by any program, and ~/.bashrc is a configuration file for interactive bash instances. You should not define environment variables in ~/.bashrc . The correct place to define environment variables such as PATH is ~/.profile (or ~/.bash_profile if you don't need non-bash shells). See what is the difference between them and which one should I use?

Notes on non-bash shells

In bash, ksh and zsh, export is a special syntax and both PATH=~/opt/bin:$PATH and export PATH=~/opt/bin:$PATH do everything right. In other Bourne/POSIX shells such as dash (which is /bin/sh on many systems), export is parsed as a regular command, which implies two differences:

  • ~ is only parsed at the beginning of a word, except for assignments (see "How to add a source directory path to be discovered by Unix, what command?").
  • $PATH outside double quotes breaks if PATH contains spaces or \[*? ,

Thus, in dash-like shells, export PATH=~/opt/bin:$PATH sets PATH to the literal string ~/opt/bin/: followed by the value of PATH up to the first place. PATH=~/opt/bin:$PATH (fuzzy assignment) doesn't require quotes and does the right thing. If you want to use export in a portable script, you need to write export PATH="$HOME/opt/bin:$PATH" .

¹ This was not true in Bourne rockets (as in a real Bourne shell, not modern POSIX-style shells), but you're not likely to run into such old shells these days.

It works anyway, but they don't do the same thing: PATH elements are checked from left to right. In the first example executable files in ~/opt/bin will take precedence over those set in /usr/bin for example, which may or may not be what you want.

In particular, from a security point of view, it's dangerous to add paths to the front, because if someone can get write access to your ~/opt/bin , they can, for example, put other ls you "d" then, probably use /bin/ls instead without noticing.Now imagine doing the same for ssh or your browser or choice... (The same can be done thrice in your path.)

Question 2 confuses me (since it was removed from the question as it was related to an unrelated issue):

What effective method adding additional paths to different lines? Initially I thought this might do the trick:

export PATH=$PATH:~/opt/bin export PATH=$PATH:~/opt/node/bin

but this is not because the second assignment not only adds ~/opt/node/bin , but also all previously assigned PATH s.

This is a possible solution:

Export PATH=$PATH:~/opt/bin:~/opt/node/bin

but for readability I'd rather have one destination per path.

If you say

PATH=~/opt/bin

this is all, what will be in your PATH. PATH is just an environment variable and if you want to add to PATH you need to rebuild the variable with exactly the content you want. So what you give as an example to question 2 is exactly what you want to do, unless I completely miss the point of the question.

I use both forms in my code. I have a generic profile that I install on every computer I work on that looks like this to accommodate potentially missing directories:

Export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11 # add optional items to the path for bindir in $HOME/local/bin $HOME/bin; do if [ -d $bindir ]; then PATH=$PATH:$(bindir) fi done

Linux defines an executable search path from the $PATH environment $PATH . To add the /data/myscripts directory to the top of your $PATH environment, use the following:

PATH=/data/myscripts:$PATH

To add this directory to the end of the path, use the following command:

PATH=$PATH:/data/myscripts

But the previous ones are not enough, because when you set an environment variable inside a script, that change only takes effect inside the script. This limitation is limited in only two ways:

  • If you export an environment variable in a script, it is effective within any program called by the script. Note that this is not effective in a program called a script.
  • If the program calling the script does so by including instead of calling, any environment changes in the script are effective in the calling program. This inclusion can be done with the dot command or the source command.

$HOME/myscript.sh source $HOME/myscript.sh

Inclusion basically includes the "invoked" script in the "invoking" script. This is similar to #include in C. Thus, it is effective inside a script or calling program. But of course this is not effective for any programs or scripts called by the calling program. To make it effective up to the call chain, you must follow the setting of the environment variable with the export command.

As an example, the bash shell program includes the contents of the .bash_profile file upon inclusion. So adding the following 2 lines to .bash_profile:

PATH=$PATH:/data/myscripts export PATH

effectively puts those 2 lines of code into a bash program. Thus, in bash variable$PATH includes $HOME/myscript.sh , and because of the export statement, any programs called by bash have their $PATH changed. And since any programs run from a bash prompt are called by bash, the new path is in effect for anything you run from a bash prompt.

The bottom line is that in order to add a new directory to the path, you need to add or prepend the directory to the $PATH environment variable in a script included with the shell, and you must export the $PATH environment's $PATH .

Additional Information here

For some time I have kept with me the two functions pathadd and pathrm which help you add elements to a path without having to worry about duplications.

pathadd takes one path argument and an optional after argument which, if added, will be added to PATH otherwise it will add it.

In almost every situation, if you add a path, you probably want to override whatever is already in the path, which is why I prefer to add the default.

Pathadd() ( newelement=$(1%/) if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then if [ " $2" = "after" ] ; then PATH="$PATH:$newelement" else PATH="$newelement:$PATH" fi fi ) pathrm() ( PATH="$(echo $PATH | sed -e "s; \(^\|:\)$(1%/)\(:\|\$\);\1\2;g" -e "s;^:\|:$;;g" -e "s ;::;:;g")" )

Put them in any script you want to change the PATH environment and you can now do so.

pathadd "/foo/bar" pathadd "/baz/bat" after export PATH

You are guaranteed not to append to the path if it already exists. If you now want /baz/bat to be at the start.

Pathrm "/baz/bat" pathadd "/baz/bat" export PATH

Now any path can be brought to the front if it is already on the path without doubling it.

I can't speak for other distributions, but Ubuntu has a file, /etc/environment, which is the default search path for all users. Since my computer is only used by me, I put whatever directories I want in my path, as long as it's a temporary addition that I put into the script.

Here is my solution:

PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: "!x[$0]++" | sed "s/\(.*\).\(1\)/\1 /")

Nice light liner that doesn't leave trailing:

For me (on Mac OS X 10.9.5) adding a pathname (e.g. /mypathname) to the /etc/paths file worked very well.

Before editing, echo $PATH is returned:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

After editing /etc/paths and restarting the shell, the $PATH variable is added with /pathname . Indeed, echo $PATH returns:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

It happened that /mypathname was added to $PATH .

To add a new path to the PATH environment PATH:

Export PATH=$PATH:/new-path/

To make this change apply to every open shell, add it to the file that the shell will call when it is invoked. In different shells, this can be:

  • Bash Shell: ~/.bash_profile, ~/.bashrc or profile
  • Korn Shell: ~/.kshrc or .profile
  • Z Shell: ~/.zshrc or .zprofile

for example

# export PATH=$PATH:/root/learning/bin/ # source ~/.bashrc # echo $PATH

You can see the provided path in the above output.

When you enter the command in command line, you are basically telling the shell to run the executable with the given name. On Linux, these executable programs like ls, find, file, and others tend to live in several different directories on your system. Any file with executable permissions stored in these directories can be run from anywhere. The most common directories that contain executable programs are /bin, /sbin, /usr/sbin, /usr/local/bin, and /usr/local/sbin.

But how does the shell know which directories to search for executable programs, or does the shell search the entire file system?

The answer is simple. When you issue a command, the shell searches all directories specified in the user's $PATH variable for an executable file with that name.

This article shows you how to add directories to your system $PATH .

What is $PATH in Linux

The $PATH environment variable is a colon-delimited list of directories that tells the shell which directories to search for executable files.

To check which directories you have in your $PATH variable, you can use the printenv or echo command:

echo $PATH

The output will look something like this:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

If you have two executables with the same name located in two different directories, the shell will run the file that is in the directory that comes first in $PATH.

Adding a directory to your $PATH

There are situations where you may want to add other directories to the $PATH variable. For example, some programs may be installed in different locations, or you may want to have a dedicated directory for your personal entries, but be able to run them without specifying the absolute path to the executables. To do this, you just need to add the directory to your $PATH.

Let's say you have a directory called bin located in your home directory where you keep your shell scripts. To add a directory to your $PATH:

The export command exports the modified variable to the shell's child process environments.

Now you can run your scripts by simply typing the name of the executable script without specifying the full path to the executable file.

However, this change is temporary and only affects the current shell session.

To make the change permanent, you need to define the $PATH variable in your shell's configuration files. On most Linux distributions, when starting a new session, environment variables are read from the following files:

  • Global shell configuration files such as /etc/environment and /etc/profile. Use this file if you want the new directory to be added to everyone system users$PATH.
  • Configuration files for individual user shells. For example, if you are using Bash, you can set the $PATH variable in the ~/.bashrc file, and if you are using Zsh, the file name is ~/.zshrc.

In this example, we will set a variable in the ~/.bashrc file. Open the file in text editor and add the following line at the end:

Nano ~/.bashrc

Export PATH="$HOME/bin:$PATH"

Save the file and load the new $PATH into the current shell session using :

Source ~/.bashrc

To confirm that the directory was added successfully, print its $PATH value by typing:

echo $PATH

Conclusion

Adding new directories to your user or global $PATH is fairly easy. This allows you to execute commands and scripts stored in non-standard locations without having to enter the full path to the executable.

The same instructions apply to any Linux distribution, including , CentOS, RHEL, Debian and Linux Mint.

Feel free to leave comments if you have any questions.

I'm wondering where the new path should be added to the PATH environment variable. I know this can be done by editing .bashrc (for example), but it's not clear how.

In this way:

Export PATH=~/opt/bin:$PATH

Export PATH=$PATH:~/opt/bin

11 responses

simple material

PATH=$PATH:~/opt/bin PATH=~/opt/bin:$PATH

depending on whether you want to add ~/opt/bin at the end (to search all other directories if there is a program with the same name in multiple directories) or at the beginning (to search before all other directories).

You can add multiple entries at the same time. PATH=$PATH:~/opt/bin:~/opt/node/bin or changes in collation just fine.

You don't need to export if the variable is already in the environment: any change to the variable's value is reflected in the environment.¹ PATH is pretty much always in the environment; all unix systems install it very early (usually in the very first process, in fact).

If your PATH is created by many different components, you may end up with duplicate entries. See How to add a home directory path that will be discovered by Unix, which command? and Remove duplicate $PATH entries with awk command to avoid duplication or remove them.

Where to put

Note that ~/.bash_rc is not readable by any program, and ~/.bashrc is a configuration file for interactive bash instances. You should not define environment variables in ~/.bashrc . The correct place to define environment variables such as PATH is ~/.profile (or ~/.bash_profile if you don't like shells other than bash). See What is the difference between them and which one should I use?

Notes on non-bash shells

In bash, ksh and zsh, export is a special syntax, and both PATH=~/opt/bin:$PATH and export PATH=~/opt/bin:$PATH do the right thing even. In other Bourne/POSIX shells, such as dash (which is /bin/sh on many systems), export is parsed as a normal command, which implies two differences:

  • ~ is only parsed at the beginning of a word, except for assignments (see How do I add a path to a home directory that will be discovered by Unix that requires a command? ;
  • $PATH external double quotes breaks if PATH contains spaces or \[*? .

So, in shells like dash, export PATH=~/opt/bin:$PATH sets PATH to the literal string ~/opt/bin/: followed by the value of PATH up to the first place. PATH=~/opt/bin:$PATH (simple assignment) doesn't require quotes and does the right thing. If you want to use export in a portable script, you need to write export PATH="$HOME/opt/bin:$PATH" or PATH=~/opt/bin:$PATH export PATH (or PATH=$HOME/opt/bin: $PATH export PATH for portability even to the Bourne shell, which doesn't accept export var=value and didn't do tilde expansion).

¹ This was not true in Bourne shells (like the actual Bourne shell, not modern POSIX-style shells), but you're not likely to run into those old shells these days. Sub>

Either way works, but they don't do the same thing: PATH elements are checked from left to right. In the first example, executables in ~/opt/bin will take precedence over those installed in /usr/bin for example, which may or may not be what you want.

In particular, it's dangerous from a security point of view to add paths to the front, because if someone can get write access to your ~/opt/bin , they can put another ls for example, which you'll probably use instead /bin/ls without noticing. Now imagine doing the same for ssh or your browser or choice... (Three times put the same on your path.)

I'm confused about question 2 (since it was removed from the question since it was linked to not related problem):

What is an efficient way to add additional paths to different lines? Initially I thought this might do the trick:

export PATH=$PATH:~/opt/bin export PATH=$PATH:~/opt/node/bin

But that's not because the second assignment not only adds ~/opt/node/bin , but also the previously assigned PATH .

This is a possible workaround:

Export PATH=$PATH:~/opt/bin:~/opt/node/bin

But for readability, I'd rather have one destination per path.

If you say

PATH=~/opt/bin

this is all, which will be in your PATH. PATH is just an environment variable and if you want to add to PATH you need to rebuild the variable with exactly the content you want. That is, what you give as an example to question 2 is exactly what you want to do, if I haven't completely missed the point of the question.

I use both forms in my code. I have a generic profile that I install on every machine I work on that looks like this to host potentially missing directories:

Export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11 # add optional items to the path for bindir in $HOME/local/bin $HOME/bin; do if [ -d $bindir ]; then PATH=$PATH:$(bindir) fi done

Linux defines an executable search path with the $PATH environment variable. To add the /data/myscripts directory to the beginning of the $PATH environment variable, use the following:

PATH=/data/myscripts:$PATH

To add this directory to the end of the path, use the following command:

PATH=$PATH:/data/myscripts

But the previous ones are not enough, because when you set an environment variable inside a script, that change only takes effect inside the script. This limitation is limited in two ways:

  • If you export an environment variable inside a script, it is effective within any program called by the script. Note that this is not effective in the program that called the script.
  • If the program calling the script does so by including instead of calling, any environment changes in the script are effective in the calling program. This inclusion can be done with the dot command or the source command.

$HOME/myscript.sh source $HOME/myscript.sh

Inclusion basically includes the "invoked" script in the "invoking" script. This is similar to #include in C. Thus, it is effective inside a script or calling program. But of course this is not effective for any programs or scripts called by the calling program. To make it effective up to the call chain, you must follow the setting of the environment variable with the export command.

As an example, the bash shell program includes the contents of the .bash_profile file upon inclusion. So put the following 2 lines in .bash_profile:

PATH=$PATH:/data/myscripts export PATH

effectively puts those 2 lines of code into a bash program. So in bash, the $PATH variable includes $HOME/myscript.sh , and because of the export statement, any programs called by bash have their $PATH variable changed. And since any programs you run from a bash prompt are called by bash, the new path applies to anything you run from a bash prompt.

The bottom line is that in order to add a new directory to the path, you need to add or prepend the directory to the $PATH environment variable in a script included with the shell, and you must export the $PATH environment variable.

For some time now, I've kept with me the two functions pathadd and pathrm , which help you add elements to a path without worrying about duplications.

pathadd takes one path argument and an optional after argument which, if added, will be added to PATH , otherwise it will add it.

In any situation, if you're adding a path, you probably want to override whatever's already in the path, which is why I prefer to add the default.

Pathadd() ( newelement=$(1%/) if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then if [ " $2" = "after" ] ; then PATH="$PATH:$newelement" else PATH="$newelement:$PATH" fi fi ) pathrm() ( PATH="$(echo $PATH | sed -e "s; \(^\|:\)$(1%/)\(:\|\$\);\1\2;g" -e "s;^:\|:$;;g" -e "s ;::;:;g")" )

Put them in any script you want to change the PATH environment and now you are good to go.

pathadd "/foo/bar" pathadd "/baz/bat" after export PATH

You are guaranteed not to add the path if it already exists. If you want /baz/bat to be started at the beginning.

Pathrm "/baz/bat" pathadd "/baz/bat" export PATH

Now any path can be moved to the front if it is already on the path without doubling it.

Bulletproof way to add/pre-treat

There are many considerations involved in the choice of add and add. Many of these are covered in other answers, so I won't repeat them here.

The important point is that even if system scripts don't use this (I wonder why) * 1 , a bulletproof way to add a path (e.g. $HOME/bin) to the PATH environment variable

PATH="$(PATH:+$(PATH):)$HOME/bin"

to add (instead of PATH="$PATH:$HOME/bin") and

PATH="$HOME/bin$(PATH:+:$(PATH))"

to add (instead of PATH="$HOME/bin:$PATH")

This avoids a false leading/trailing colon when $PATH is initially empty, which can have unwanted side effects and can be a nightmare to find elusively (this answer briefly addresses the awk-way case).

$(parameter:+word)

If parameter has null or unset, nothing is replaced, in otherwise the word word is replaced.

So $(PATH:+$(PATH):) expands to: 1) nothing if PATH is null or unset, 2) $(PATH): if PATH is set.

Note. This is for bash.

*1 I just found that scripts like devtoolset-6/enable actually use this $ cat /opt/rh/devtoolset-6/enable # General environment variables export PATH=/opt/rh/devtoolset-6/root/usr /bin$(PATH:+:$(PATH)) ...

I can't speak for other distributions, but Ubuntu has a file /etc/environment which is the default search path for all users. Since my computer is only used by me, I put whatever directories I want on my path there, unless it's a temporary addition I put into the script.

For me (on Mac OS X 10.9.5) adding a pathname (e.g. /mypathname) to the /etc/paths file worked just fine.

Before editing, echo $PATH is returned:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

After editing /etc/paths and restarting the shell, the $PATH variable is added with /pathname . Indeed, echo $PATH returns:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

It happened that /mypathname was added to the $PATH variable.

A computer