Environment Variables

When you launch an executable, or run a command, the operating system spawns something called a process. A processes is a representation of a running program that Windows uses internally. We won’t go deeply into what makes up a process, but we do need to think a little about how processes are related to one another in order to make sense of the topic of this chapter.

If you think about it, the spawning of a process is typically triggered from within another process. Launching a program from the start menu, the program you launch is called a child process, and the desktop itself is the parent process. When you execute a command on the Command Prompt, the Command Prompt is the parent, and the command (say notepad) is the child. Going even further, the Command Prompt is a child process of Windows Console, which is itself a child process of the desktop.

You can think of all of the processes running on your computer as residing in a hierarchy of parent-child relationships, just like these, going all the way up to a single parent process for the whole system, which is started when you first boot the computer.

The reason for bringing this up is because there is information inherited by child processes from their parents, and this information is the topic of this chapter: environment variables.

Environment Variables

There are a set of variables (exactly like the ones we discussed in the previous chapter) that constitute a process’s environment. These variables, and their values, are inherited directly from the process’s parent.

In Command Prompt, technically every variable is part of the shell’s environment.1 What this means is that any time you call set to create a variable,

% set var=123

you are adding this variable to your shell’s environment. Any command that you execute from within your shell will inherit and have access to this variable. To demonstrate this with an (admittedly pretty contrived) example, try creating a variable, and then running the cmd command. This will launch a new Command Prompt shell running as a child to your original one (in the same Console). Then, try echoing the variable that you defined,

% set x=hello there
% cmd
Microsoft Windows <version>
% echo %x%
hello there

Now we’ll try the same thing in reverse. Define a new variable here, in the child process. Then use exit to close out of the child and return to the parent. Try printing the variable that you defined, it should fail

% set y=goodbye now
% exit
% echo %y%
%y%

This happens because the child inherits copies of all of the variables defined in the parent at the time of its creation, and so it can access x. However, any changes to the child’s environment remain in the child, and die when it is closed. They are never propagated back to the parent. Additionally, we can verify pretty easily that the child only gets copies by trying to change an inherited variable, and seeing if that change is reflected in the parent,

% set x=hello there
% cmd 
Microsoft Windows <version>
% set x=goodbye now
% exit
% echo %x%
hello there

Yup! As you can see, the child gets a copy of the parent’s environment, but after that point the two diverge. Any changes to the child’s environment won’t affect the parent, and likewise any future changes to the parent’s environment won’t affect the child.2

Every shell variable being a part of the environment is another of Command Prompt’s idiosyncrasies. In bash, for example, shell variables are not part of the environment by default, but can be added to the environment manually using the export command.

Showing the Environment

You can see what variables are defined within your shell’s environment by running the set command without any arguments. This will produce a list of all of the variables currently defined, and their current values. You’ll see that there are quite a few!

% set
variable=value
othervariable=othervalue
...

In Windows, most of these variables and their values ultimately come from the System Registry, a centralized configuration database built into the operating system. Software that you install may add configuration variables to the registry as part of their installation, and a lot of these variables are predefined by Windows itself.

Notable Environment Variables

USERPROFILE

The first variable we’ll look at is USERPROFILE. You can see what your USERPROFILE is by either finding it in the output of set, or just echoing it (note: just like with commands, variable names are not case sensitive in Command Prompt, so capitalization doesn’t matter, but it is convention to use ALL CAPS for environment variables and lowercase for local variables),

% echo %USERPROFILE%
C:\Users\douglas

This variable contains your user account’s home directory. The variable name is a little inconveniently long, sadly, but this variable can be used to quickly return to your home directory via cd,

% cd %USERPROFILE%

PROMPT

The PROMPT environment variable contains the text of your prompt, and can be changed to configure it. As a somewhat silly example,

C:\Users\douglas>set PROMPT=this is a prompt>
this is a prompt>

There is actually a command, also called prompt, which you can use to customize this as well. And there are various special character sequences you can add to the PROMPT variable to fill in various information dynamically, such as your current working directory, the current data and time, etc. You can get a lot of information about prompt customization with,

% prompt /?

Have fun! You can reset your prompt to the default at any time by running the prompt command without arguments,

% prompt

USERNAME

This variable contains your username–pretty straightforward.

% echo %USERNAME%
douglas

PATH

The PATH variable is one of the most important environment variables from the perspective of using the command line shell. If you look at the contents of this variable, you’ll see it is a semi-colon separated list of directories,

% echo %PATH%
C:\Program Files\someprog\;C:\Program Files\anotherprog\;...

These directories are the locations in which the Command Prompt will look for commands when you execute them.

You may have noticed that many programs that you have installed on your machine cannot be launched from the command line, while others can. For example, we can easily launch notepad,

% notepad afile.txt

but we cannot launch a web browser,

% vivaldi
'vivaldi' is not recognized as an internal or external command,
operable program, or batch file.

This is because the notepad.exe file on our computer is located in one of the directories listed in PATH, but (in this case) vivaldi.exe is not. Thus, it follows that if we want to launch Vivaldi (or any other program) from the command line, we need to locate it, and add the directory containing it to the path.

A few chapters back, we learned how to search for files on our system, so let’s do that to locate our web browser. If you don’t know the name of the executable file for your browser precisely, you can use wildcards. Also, remember that once the search finds the file you want, you can abort it with ctrl+C (^C), rather than waiting for it to finish scanning your whole drive.

% cd C:\
% dir /s vivaldi.exe
 Volume in drive C is Local Disk
 Volume Serial Number is 44C6-3E83

 Directory of C:\Users\douglas\AppData\Local\Vivaldi\Application

01/11/2023  09:27     1,983,336   vivaldi.exe
...

You’ll want to find the corresponding executable file, so it will likely have a .exe extension. Once you’ve found it, you want to add the directory containing it to your path. This can be done using set,

% set PATH=%PATH%;<your directory here>

MAKE SURE YOU HAVE %PATH% AS PART OF THE VALUE YOU ASSIGN. This will ensure that your new PATH still contains all of the directories of the old one, just with your web browser’s directory added on to it. If you forget to do this, you’ll find that many commands will no longer work (because they aren’t on the path anymore).

Once you’ve updated the path, you should be able to launch your web browser (or any other program) by typing the name of its executable file into the shell. Recall, as we saw with notepad originally, that you don’t need to type the extension. So in this case, I could open my browser to this website using

% vivaldi douglasrumbaugh.com

Making Changes to Environment Variables Persistent

After adding a directory to your path, you will be able to launch programs from that directory within the current shell, and any child processes you spawn from it. But, any other shells you launch that are not children of the current one will not get this new value for PATH, and so will not be able to launch those programs.

If you want to persist the new path value, you’ll need to add it to the system registry. There’s actually a graphical interface for doing this–if you punch “environment variables” into Windows search it should pop right up–but you can also do it from the command line using another command, setx.

The setx command allows you to permanently set values for environment variables, so that any and all new shells that you launch will get the new value.

First, you should set up your path as we did above, to verify that your value is correct and doesn’t break anything. If you mess it up with set, you just need to close the terminal and the change will be reverted. If you mess it up with setx, it won’t be nearly as easy to fix.

For historical reasons, setx will only allow a maximum of 1024 characters in the value of the variable being set. If your new path is longer than this, it will be truncated.

If your path is relatively short, it should be fine to use this command to add a few directories to it. But once your path gets longer, it’s probably safer to just use the GUI to set it up.

Once you’re ready, you can add a directory permanently to your path with,

setx PATH %PATH%;<your directory here>

If you begin using the command line heavily, you’ll probably find that your path grows quite long on Windows. Linux tends to put all of the executables in a few common spots, whereas Windows likes to put each program in its own directory.

Presumably, a long path might hurt performance (as the shell needs to look in more places before it finds the command), but I’ve never noticed any slowdown to having a long path. If you do, one trick you can play is to put the directories containing more important programs at the beginning–the shell just does a linear scan of the directories until it finds what it is looking for, so putting your frequently used stuff at the front of the queue should speed things up.

Conclusion

In this chapter, we discussed the concept of an environment, a set of variables inherited by each process from its parent, and how to add and edit variables within the environment, as well as a few important environment variables from the perspective of Command Prompt. Using this information, we discussed how to set up new programs to be called from the command line, by adding them to the PATH variable.

In the next chapter, we’ll discuss files: how to write the results of a command to a file, read input from a file, and link commands together using pipelines.


  1. There is one exception, which we won’t encounter in this tutorial. Variables defined between setlocal and endlocal commands within a batch file are not persisted within the shell’s environment. ↩︎

  2. This one is a bit harder to show with the tools we have at the moment, so you’ll have to take it on faith. I promise though, it is true! ↩︎

Previous
Next