An introduction to the most useful special and environment variables in Bash

https://www.profitableratecpm.com/f4ffsdxe?key=39b1ebce72f3758345b2155c98e6709c

Are you currently learning Bash? Have you seen things like $0 And $EUID and I wondered what they meant? Or what is the difference between $UID And $EUID? I’ll talk about them and more: what they do and why they’re important.

Complete HTG Wrapped Calendar - December 24

HTG Wrapped 2025: 24 days of technology

24 days of our favorite hardware, gadgets and technologies

Special settings

Special parameters are variables provided by Bash for specific purposes. There are less than 10, and the following seem the most useful to me.

Get the script path

Sometimes when you write a script you want to know its path. For example, when creating a help menu, it is customary to include the name of the script at the top. Here is the help menu for the ls command:

ls --help
A terminal window displays the output of the ls command. It points out that the command name is visible in the help menu.-1

You can access the (relative) path using the $0 special parameter. This is a POSIX standard, so you can use it in most shells:

echo "$0"
A terminal window displays a relative path to a script.

Then you can get the script name using $(basename $0):

A terminal window displays the name of a script: script.sh.

However, sometimes $0 is unreliable; for example, the source /path/to/script.sh returns “bash” and not the script path. Instead, use the $BASH_SOURCE variable, which works almost identically, except without surprises. If you only use Bash, it’s the best choice, but it’s not portable to other shells.

Determining the exit status of a process

Each program returns a number as output. This is called the exit code and is used to make decisions when a command returns an error. For example, if you try to ls a non-existent directory, it returns a non-zero value.

A zero exit status means success; a non-zero value indicates a problem.

When you encounter a problem, you may want to pause execution and $? a special parameter provides the necessary exit code:

ls /system32
echo $?
A terminal window displays an error message from the ls command. It indicates that the queried directory does not exist. It also displays the number 2.-1

There are several ways to detect and handle an exit code. The most obvious is to evaluate “$?” with a conditional statement:

if [[ $? -eq 0 ]]; then
   # If the script executed successfully.
fi

The exit code usually means something and is program specific, but you can handle distinct values ​​with a case statement:

case $? in
  0) echo "OK";;
  1) echo "Err";;
  *) echo "Unhandled error";;
esac

One of my favorite approaches is to use a conditional statement without brackets:

if ls /system32; then
  # Upon zero exit code.
  echo "/system32 exists"
fi

But the most elegant solution is to use logical operators:

ls /system32 && echo "/system32 exist" # && executes on zero exit status.
ls /system32 || echo "/system32 does not exist" # || executes on non-zero exit status.

Access arguments

If you write a Bash script, you will invariably need to pass it values, i.e. arguments or positional parameters. Bash’s approach is a bit clunky, but it works. Examples are the easiest way to understand them:

foo() {
  echo "$1" # First argument.
  echo "$2" # Second argument.
}
foo "first" "second"

I passed arguments into a function, but they work exactly the same at the top level of your script. For example:

#!/usr/bin/env bash
# This is the top-level of your script.
echo "The first argument: $1"
echo "The second argument: $2"

You can then pass arguments into your script via the CLI: script.sh "first" "second".

Then, the special parameter “$@” represents all arguments as an array:

foo() {
  for arg in "$@"; do
    echo "$arg"
  done
}
foo "first" "second"
A terminal window displays the words first and second on two lines.

The special parameter “$*” is the same as “$@”, except that it puts all arguments into a single string (if “$*” has double quotes):

at() {
  printf '@: [%s]\n' "$@"
}

star() {
  printf '*: [%s]\n' "$*"
}

at   "one two" "three"
star "one two" "three"
A terminal window displays the results of the special “at” and “star” variables. The “at” variable has its contents printed on several lines and the “star” variable on a single line.

You can see that “$@” prints both arguments on two lines, but “$*” prints them on a single line.

To get the number of arguments you can use the ${#@} Or ${#*} syntax:

foo() {
  echo ${#@}
  echo ${#*}
}
foo "one" "two"
A terminal window displays the number 2 twice, on two lines.

Environment variables

Environment variables are values ​​provided to running programs by the shell. For example, $HOME provides the path to the current user’s home directory.

Get User ID

Sometimes I need to know the current user id in a script. For example, recently I was interacting with a socket in the /run/user/1000 directory. The “1000” is the user ID, and if we want a robust script, we should not hardcode this value, because another user running it may have a different user ID.

To solve this problem we can use the $UID And $EUID variables. “$UID” displays the ID of the user running a binary. “$EUID” (effective user ID) is the user ID of the process executing a binary. Normally these are equal, but for setuid binaries they may differ. For example, when running something with sudo, they vary as the fork progresses through different stages.

ps --forest -eo cmd,euid,ruid | grep -C 1 '[s]udo'
A terminal window displays a tree of forked processes. This shows that running the set UID binaries changes the UID and EUID from 1000 to 0.

I have “sudo sleep 600” running in the background and the prompt above shows the command columns, EUID (“1”) and UID (“2”) for any process running sudo. You can see that the EUID immediately becomes “0”, but the UID does not change until the final forked process (which is “dormant” running as root).

Tux, the Linux mascot, wears sunglasses and looks out from behind a large terminal window displaying global commands.

8 Linux Shell Tricks That Completely Change How Commands Work

The shell does much more than just run commands. Here’s how Bash extends your typing behind the scenes so you can write cleaner, more reliable commands.

What can we learn from it? Well, it doesn’t matter which one you use. Some say to use “$EUID” to check if you have root privileges, as those are the effective permissions. However, you can see in the image that the final “sleep” process has both the UID and EUID set to “0” (root), and the shell process is both set to “1000” (user). These represent either end of the fork process, where you issued the sudo request as well as the final execution process. Therefore, there is no useful distinction between them when it matters, but remember that they differ for setuid binaries during the fork process.

Get common user paths

In almost every script I write, I access the home directory. Less frequently, I need access to ~/.config Or ~/.local/share. Accessing typical locations in the filesystem is common, but hardcoding paths like this is bad practice because they can change. The recommended approach is to use the XDG directory specification, which is a set of standard variables provided by freedesktop.org.

env | grep XDG | sort -u
A terminal window displays a list of nine XDG variables, consisting of paths and non-path values.-2

Not all variables are defined and some are not paths.

When using XDG variables, always set a reasonable default value:

export "${XDG_CACHE_HOME:=$HOME/.cache}"

This will also set the variable (if it’s not set) and make it available to any binaries or scripts you run.

The most common variables I use:

export "${XDG_CACHE_HOME:=$HOME/.cache}"       # Semi-temporary data.
export "${XDG_CONFIG_HOME:=$HOME/.config}"     # Configuration files.
export "${XDG_DATA_HOME:=$HOME/.local/share}"  # Downloaded data, etc.

There are several others and I encourage you to learn them. You should use these locations instead of writing everything in /tmp or a custom directory in ~/.

Konsole terminal opened on Linux Kubuntu Focus Ir14 laptop.

How to get a cheat sheet for any command in Linux Terminal

Sometimes cheating is necessary.


In addition to these variables, many useful environment variables are available through the shell. The variables covered represent the ones I use most often. I couldn’t write Bash scripts without them. Conversely, hardcoding values ​​will eventually lead to breakages. When you have hundreds of scripts, such failures become a maintenance nightmare. Therefore, it is best to infer as much as possible from elsewhere, preferably from standard variables, and the variables presented here today fit the bill perfectly.

In conclusion, learn and use as many standard variables as possible.

A terminal window displaying sample Bash script output, accompanied by shell and .sh icons.

3 Bash Scripting Techniques Every Linux User Should Know

Unleash the power of Bash with these simple techniques.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button