Test Operators in Bash

When you dig down Linux a little bit, you realize it heavily relies on the bash scripts and when you open bash scrips, you see lots of symbols like !=, -lt, and ==.

And I'm pretty sure if you're not into programming, they'd look confusing.

So in this tutorial, I will walk you through examples of every test operator available in the bash.

But before I walk you through the examples part, let's have a look at what test operators you get in bash and their usage.

List of test operators in bash

Test operators in bash scripts help you evaluate the conditions such as you may want to execute a specific block of code based on whether the condition is true or not.

And here's a list of test operators you get in bash:

Test operators for integer comparison

Bash Operator Meaning
-eq Equal to
-ne Not equal to
-lt Less than
-le Less or equal to
-gt Greater than
-ge Greater or equal to
<= Less or equal to (used inside (()))
>= Greater or equal to (used inside (()))

Bash test operators for compound comparison

Bash Operator Meaning
-a Logical AND operator, similar to &&
-o Logical OR operator, similar to ||

String comparison operators

Bash Operator Meaning
= Equals to (but for strings)
!= Not equal to (for strings)
< Less than (in ASCII alphabetical order)
> Greater than (in ASCII alphabetical order)
== Double equals to (used to compare two strings)
-z The String is null
-n The String is not null

File test operators

Bash Operator Meaning
-e Check whether the file exists at a given path.
-f Check whether the given file path points to a regular file or not.
-d Check whether the given path refers to an existing directory or not.
-h Finds whether the given path is a symbolic link.
-L It checks for the symbolic link as the -h does, but it will also check whether it resolves to an actual file or directory.
-b Checks for the block device.
-c Checks for the character special file.
-p Checks for a named pipe (FIFO).
-s Used to find whether the file size is greater than zero or not.
-t Check whether the file descriptor is associated with the terminal or not.
-r Used to find whether the file is readable or not.
-w Checks for whether the file is write permissions or not.
-x It checks for the executable permissions for a specified file.
-g Checks for "set-group-ID" (SGID) permission set on a specific file.
-u Checks for "set-user-ID" (SUID) permission set on a specific file.
-k Look for the "sticky" bit is set or not on a specified directory.
-O Check whether the file exists and is owned by the current user.
-G Check whether the file exists and is owned by the same group as the user running the script.
-N Helps you check if the file has been modified since it was last read.
-nt Compares modification time of two files and determines which one is newer.
-ot This too compares the modification time of two files and determines which one is older.
-ef Check whether two file paths refer to the same inode on the system.
! Reverses the result of a condition or command.

Now, let's take a look at examples of each test operator that I listed above.

Examples of test operators in bash

This section is divided into four categories:

  • Integer comparison operators
  • String comparison operators
  • Compound comparison
  • File test operators

So let's start with the first one.

Integer comparison operators

The integer comparison operators in bash are used to compare integer values with conditional statements.

Using these operators, you can compare two integers in various ways such as equality, inequality, greater than, less than, etc.

So let's have a look at integer comparison operators in bash with examples.

1. The -eq (equal to)operator

The -eq operator in bash is used to compare two numeric values and check if they are equal.

For more understanding, here, I used a simple bash script which will compare two values and print whether they are the same or not:

#!/bin/bash

number1=5
number2=5

if [ "$number1" -eq "$number2" ]; then
    echo "The numbers are equal."
else
    echo "The numbers are not equal."
fi

When I executed the above script, it gave me the following output:

As you can see, the number1 and the number2 variables were holding the same value so it gave me output saying "The numbers are equal".

2. The -ne (not equal to) operator

The -ne operator does the opposite of the -eq by comparing two operators to check if they are not equal.

For your reference, here's a similar bash script as above but this time, I have used different values for both variables:

#!/bin/bash

number1=5
number2=10

if [ "$number1" -ne "$number2" ]; then
    echo "The numbers are not equal."
else
    echo "The numbers are equal."
fi

When I executed the above script, it gave me output saying the variables are not equal:

3. The -lt (less than) operator

As the name suggests, using the -lt operator, you can determine whether the first variable is lesser than the second variable.

Here's a simple script where I have compared two variables to check whether the number1 is lesser then number2 or not:

#!/bin/bash

number1=5
number2=10

if [ "$number1" -lt "$number2" ]; then
    echo "number1 is less than number2."
else
    echo "number1 is not less than number2."
fi

When I ran the above script, it gave me the following output saying the number1 is less than the number2:

4. The -le (less or equal to) operator

As the name suggests, the -le operator is used to compare two integer values and check whether the first integer is less or equal to the second.

Here's a simple bash script explaining how you can use the -le operator:

#!/bin/bash

number1=5
number2=10

if [ "$number1" -le "$number2" ]; then
    echo "number1 is less than or equal to number2."
else
    echo "number1 is greater than number2."
fi

Can you guess the output? The number1 should be less or equal to the number2 and it gave me the same output when I executed the above script:

5. The -gt (greater than) operator

The -gt operator is used to compare two values and find out if the first variable is greater than the second one.

Here's how you can use the -gt operator in bash to compare two variables:

#!/bin/bash

number1=10
number2=5

if [ "$number1" -gt "$number2" ]; then
    echo "number1 is greater than number2."
else
    echo "number1 is not greater than number2."
fi

When I executed the above script, it gave me the following output saying "number1 is greater than number2":

6. The -ge (greater or equal to) operator

The -ge operator in bash is used to determine whether one integer is greater or equal to another.

For example, here's a bash script comparing two integers with the -ge operator:

#!/bin/bash

number1=10
number2=5

if [ "$number1" -ge "$number2" ]; then
    echo "number1 is greater than or equal to number2."
else
    echo "number1 is not greater than or equal to number2."
fi

The number1 should be greater or equal to the number2. Right?:

7. The < (less than) operator

When you use the < operator inside of (()), it can be used to do arithmetic comparisons between two values.

For example, here, I used < to compare two variables:

#!/bin/bash

number1=5
number2=10

if ((number1 < number2)); then
    echo "number1 is less than number2."
else
    echo "number1 is not less than number2."
fi

Here's what I got when I executed the above script:

8. The > (greater than) operator

When you use the > operator inside (()), you can compare two variables and find out which is the larger.

For example, here, I used the > operator to compare two variables:

#!/bin/bash

number1=10
number2=5

if ((number1 > number2)); then
    echo "number1 is greater than number2."
else
    echo "number1 is not greater than number2."
fi

If you execute the above script, it will give you an output saying "number1 is greater than number2.":

9. The <= (less or equal to) operator

When you use the <= operator inside of (()), it gives you the same functionality as the -le. Which means using the <= operator, you can compare two variables and find if one is less or equal to the other.

To demonstrate how you can use the <= operator, you can refer to the following script:

#!/bin/bash

number1=5
number2=10

if ((number1 <= number2)); then
    echo "number1 is less than or equal to number2."
else
    echo "number1 is greater than number2."
fi

When executed, it gave me the following output:

10. The >= (greater or equal to) operator

You guessed it right? Using the >= operator you can compare two variables and find out if one is greater or equal to the other one.

For further reference, you can use the following bash script:

#!/bin/bash

number1=5
number2=10

if ((number1 <= number2)); then
    echo "number1 is less than or equal to number2."
else
    echo "number1 is greater than number2."
fi

As the number1 variable is lesser than the number2, it gave me the following output:

String comparison operators

As the name suggests, the string comparison operators are used to compare two strings and used to determine the difference between two strings.

There are different string comparison operators such as equality, inequality, alphabetical order, and more.

So let's start with the first one.

1. The = (equal to) operator

The = operator is to compare two strings and to find out if they hold the same set of characters (string) or not.

For your reference, here, I compared two strings using the = operator:

#!/bin/bash

str1="apple"
str2="banana"

if [ "$str1" = "$str2" ]; then
    echo "str1 is equal to str2."
else
    echo "str1 is not equal to str2."
fi

As the strings in the above script hold a different value, it gave me output saying "str1 is not equal to str2.":

2. The != (not equal to) operator

The != operator in bash is used to compare two strings and determine if two strings are not equal.

For example, here, I used a simple bash script to demonstrate how you can use the != operator to compare strings:

#!/bin/bash

str1="apple"
str2="banana"

if [ "$str1" != "$str2" ]; then
    echo "str1 is not equal to str2."
else
    echo "str1 is equal to str2."
fi

Both strings str1 and str2 holds different sets of characters, it gave me output saying "str1 is not equal to str2.":

3. The == (double equals to) operator

Unlike other operators, the == behaves differently on how you quote the matching string.

  • Pattern matching
  • Literal matching (similar to the = operator)

So let's start with pattern matching.

Pattern matching using the == operator

This is a simple one. You use one string and then use conditional statements to match the pattern to find out whether the string is valid as per the pattern.

For example, here, I used a simple bash script that will find a string starting with z. (that's the reason why I used "$a" == z*):

#!/bin/bash

a="zebra"
if [[ "$a" == z* ]]; then
    echo "Pattern matched: 'a' starts with 'z'."
else
    echo "Pattern not matched: 'a' doesn't start with 'z'."
fi

As the zebra starts with the z, it gave me the following output:

Literal matching using the == operator

As the name suggests, it literally matches the string itself giving similar results to the = operator.

For your reference, here, I have used one string containing z* and did the literal matching using the == operator:

#!/bin/bash

a="z*"
if [[ "$a" == "z*" ]]; then
    echo "Literal match: 'a' is 'z*'."
else
    echo "Literal mismatch: 'a' is not 'z*'."
fi

As the string a holds the z*, it gave me the following result:

4. The < (less than) operator [for strings]

When you use the < operator inside [[]], it compares two strings and finds you which one is lesser than the other in terms of alphabetical order.

Let me give you an example for better understanding.

Here's a simple bash script that compares two strings apple and banana:

#!/bin/bash

str1="apple"
str2="banana"

if [[ "$str1" < "$str2" ]]; then
    echo "str1 comes before str2."
else
    echo "str1 does not come before str2."
fi

As the word apple comes before the word banana, it gave me output saying "str1 comes before str2.":

5. The > (greater than) operator [for strings]

Similar to the < operator, the > operator when used inside of [[]], it can be used to compare two strings and find out which one is greater than the other in terms of alphabetical order.

Here's how you can use the > operator in a bash script:

#!/bin/bash

str1="apple"
str2="banana"

if [[ "$str1" > "$str2" ]]; then
    echo "str1 comes before str2."
else
    echo "str2 comes before str1."
fi

As the string1 comes before the string2, you can expect the following output:

6. The -z operator

The -z operator in bash is used to find out if the string is empty or not.

For example, here, I used an empty string to demonstrate how you can use the -z operator in a bash script:

#!/bin/bash

my_string=""

if [ -z "$my_string" ]; then
    echo "The string is empty."
else
    echo "The string is not empty."
fi

As the string was empty, it gave me the following output:

7. The -n operator

The -n operator is quite the opposite of the -z operator as it is used to find non-empty strings.

Here's how you can implement the -n operator in a bash script to find the non-empty strings:

#!/bin/bash

string="Non-empty string"

if [ -z "$string" ]; then
    echo "The string is empty."
else
    echo "The string is not empty."
fi

As the string had some characters stored inside of it, it gave me the following output:

Compound comparison operators

The compound comparison operators in bash are also known as logical operators by which you can combine multiple expressions to form one complex expression.

There are 3 compound comparison operators in bash:

  • && (logical AND operator)
  • || (logical OR operator)
  • ! (logical NOT operator)

So let's start with the first one.

1. The && (AND) operator

If you use the && operator to combine two or more expressions, they will only be executed (will return exit status 0), if every expression is true.

For example, here's a simple script stating how every expression has to be true in order to have successful execution:

#!/bin/bash

age=25
income=50000

if [ "$age" -ge 18 ] && [ "$income" -ge 40000 ]; then
    echo "You are eligible for the loan."
else
    echo "You are not eligible for the loan."
fi

As you can see, both conditions that were combined through the && operator was true and gave me the following output:

2. The || (OR) operator

When you combine two expressions using the || operator, the execution will be successful if one of them is true.

This means if one of two expressions satisfies the given condition, it will return exit status 0 (indicating successful execution).

For example, here's a simple bash script that demands the age should be less than 18 or greater than 65:

#!/bin/bash

age=15

if [ "$age" -lt 18 ] || [ "$age" -ge 65 ]; then
    echo "You are eligible for a discount."
else
    echo "You do not qualify for a discount."
fi

As the age variable has a value of 15, it gave, it gave me the following:

3. The ! (NOT) operator

The NOT ! operator negates the effect of the operator.

In simple terms, it will alter the effect of the operator. For example, if I use the NOT operator after the =, it will make it not equal to.

Here's a simple bash script where I have initialized a variable is_raining to true and later on, I used the ! operator to negate the effect:

#!/bin/bash

is_raining=true

if ! [ "$is_raining" = true ]; then
    echo "It's not raining. You can go outside."
else
    echo "It's raining. Stay indoors."
fi

As the effect was altered, it falsified the value of the is_raining and gave me the following output:

File test operators

As the name suggests, the file test operators are used to perform various tests on files and directories.

In this section, I will walk you through multiple file test operators with simple bash script examples so you can have a better idea of how to use them.

1. The -e operator

Using the -e operator, you can check whether the file exists or not by using the absolute or the relative path.

For example, in the following bash script, I checked for if the file Hello.txt exist inside /home/sagar directory:

#!/bin/bash

user_file="/home/sagar/Hello.txt"

if [ -e "$user_file" ]; then
    echo "The file $user_file exist at the given path."
else
    echo "The file $user_file does not exist at given path."
fi

In the above script, the user_file was used to store the absolute path to the Hello.txt file and when executed, it gave me the following result:

2. The -f operator

The -f operator is used to find out whether the given path points to a normal file or not. An easy way to check for a valid input!

For example, here, I checked if the file.txt in the current working directory is a regular file or not:

#!/bin/bash

file_path="file.txt"

if [ -f "$file_path" ]; then
    echo "$file_path is a regular file."
else
    echo "$file_path is not a regular file."
fi

As I've created the file.txt file in the current working directory (in the same directory where the script is located), it gave me the following output:

3. The -d operator

The -d operator is used to test if a given point is in a directory or not.

For example, in the following script, I wanted to find out if the /home/sagar/New is directory or not with the help of the -d operator:

#!/bin/bash

directory_path="/home/sagar/New"

if [ -d "$directory_path" ]; then
    echo "$directory_path is a directory."
else
    echo "$directory_path is not a directory or does not exist."
fi

As the /home/sagar/New was a directory, it gave me the following output:

4. The -h operator

Using the -h operator, you can identify if the given path points to a symbolic link or not.

For example, here, I created a symbolic link named File_link to the Hello.txt inside my current working directory:

ln -s ~/Hello.txt Symbolic_Link

Next, I used the -h operator in the bash script to identify the symbolic link:

#!/bin/bash

link_path="File_link"

if [ -h "$link_path" ]; then
    echo "$link_path is a symbolic link."
else
    echo "$link_path is not a symbolic link or does not exist."
fi

As the File_link was a symbolic link, it gave me the following output:

5. The -b operator

The -b operator in bash is used to find out if the given file path is pointing to a block device or not.

For example, in the following bash script, I used /dev/sda to test whether the -b the operator can actually identify the block device or not:

#!/bin/bash

file_path="/dev/sda"

if [ -b "$file_path" ]; then
    echo "$file_path is a block special file (block device)."
else
    echo "$file_path is not a block special file."
fi

It gave me the following found when executed:

6. The -c operator

The -c operator in bash is used to identify whether the given file path is pointing to a character file or not.

You will find multiple character files inside the /dev/ directory which can be listed using the ls command in the following matter:

ls -l /dev/

The file permission will start with the c indicating the file is a character file:

For example, here, I wrote a script having a path to /dev/full and identify whether it is a character file or not:

#!/bin/bash

file_path="/dev/full"

if [ -c "$file_path" ]; then
    echo "$file_path is a character special file."
else
    echo "$file_path is not a character special file."
fi

It gave me the following output:

7. The -p operator

The -p operator in bash is used to identify if the given path is pointing to a named pipe (FIFO) file.

You can create a pipe file using the mkfifo command. For example, here, I created a named pipe file LHB_Sagar in the current working directory

mkfifo LHB_Sagar

Then, I used the -p operator in the bash script to verify if it actually can identify the created named pipe file:

#!/bin/bash

file_path="LHB_Sagar"

if [ -p "$file_path" ]; then
    echo "$file_path is a named pipe (FIFO)."
else
    echo "$file_path is not a named pipe."
fi

When executed, it successfully identified the named pipe file:

8. The -S operator

The -S operator in bash is used to identify whether the given file path is pointing to a socket file or not.

For example, here, I wrote a simple script to identify if the /var/run/snapd.socket file is socket file or not:

#!/bin/bash

socket_file="/var/run/snapd.socket"

if [ -S "$socket_file" ]; then
    echo "$socket_file is a socket file."
else
    echo "$socket_file is not a socket file or does not exist."
fi

It identified the socket file successfully and gave me the following output:

9. The -s operator

The -s operator in bash is to identify whether the given file path is pointing to a non-empty file or not.

For example, here, I created a simple text file named my_file.txt that contains the following line of text:

As the file my_file.txt has some text content inside, it is now a non-zero file so let's use it in the script to test the -s operator:

#!/bin/bash

file="my_file.txt"

if [ -s "$file" ]; then
    echo "$file is not empty."
else
    echo "$file is empty or does not exist."
fi

Here's what I got after executing the above script:

10. The -t operator

The -t operator in bash is used to find out whether the file descriptor is associated (stdin, stdout, and stderr) with the terminal or not.

In most cases, all the file descriptors will be associated with the terminal.

Here's a bash script that will let you know what file descriptors are associated to the current terminal session:

#!/bin/bash

if [ -t 0 ]; then
  echo "File descriptor 0 (standard input) is connected to a terminal."
else
  echo "File descriptor 0 (standard input) is not connected to a terminal."
fi

if [ -t 1 ]; then
  echo "File descriptor 1 (standard output) is connected to a terminal."
else
  echo "File descriptor 1 (standard output) is not connected to a terminal."
fi

if [ -t 2 ]; then
  echo "File descriptor 2 (standard error) is connected to a terminal."
else
  echo "File descriptor 2 (standard error) is not connected to a terminal."
fi

If you execute the above script, it will give you the following output:

But if I redirect the error datastream, it will no longer give the same output:

11. The -r operator

The -r operator in bash is used to identify whether the specified file has read permissions or not for the user running the script.

For example, here, I've used the -e operator first to check whether the Hello.txt file exists and if it does, then it will use the -r operator:

#!/bin/bash

filename="Hello.txt"

if [ -e "$filename" ]; then
  if [ -r "$filename" ]; then
    echo "File '$filename' exists and has read permission."
  else
    echo "File '$filename' exists but does not have read permission."
  fi
else
  echo "File '$filename' does not exist."
fi

When executed, it gave me the following output:

12. The -w operator

The -w operator is used to find out if the file has a write permissions for a user running a script or not.

For example, here, I have used the -e operator to validate the existence of the Hello.txt file and later on use the -w operator to find if it has write permissions:

#!/bin/bash

filename="Hello.txt"

if [ -e "$filename" ]; then
  if [ -w "$filename" ]; then
    echo "File '$filename' exists and is writable."
  else
    echo "File '$filename' exists but is not writable."
  fi
else
  echo "File '$filename' does not exist."
fi

As the Hello.txt is in the current working directory and it has write permissions for the current user, it gave me the following output:

13. The -x operator

The -x operator in bash is used to find whether the file has execution permissions or not.

For example, here, I checked the executable permissions of the Script.sh located in the current working directory:

#!/bin/bash

script_file="Script.sh"

if [ -x "$script_file" ]; then
  echo "The script '$script_file' is executable."
else
  echo "The script '$script_file' is not executable."
fi

As the file Script.sh had the execution permissions, the above script gave me the following output:

But if your file is not executable, you can use the chmod command to make the file executable. Here's a detailed guide on that topic:

How to Make a File Executable in Linux terminal?
New to Linux command line and wondering how to make a bash script or some other file executable? Here’s how to do it.

14. The -g operator

The -g operator in bash is used to find if the specified file has an SGID (Set-Group-ID)flag or not.

For those who don't know, When you enable the SGID and run a script or do any operations over a file, the group permissions of a file will be used.

So any actions that you do with the file are done if you're part of a group that owns the file.

For example, here, I used the -g operator to find if the Hello.txt file has SGID enabled or not:

#!/bin/bash

filename="Hello.txt"

if [ -e "$filename" ]; then
  if [ -g "$filename" ]; then
    echo "The SGID flag is set on '$filename'."
  else
    echo "The SGID flag is not set on '$filename'."
  fi
else
  echo "File '$filename' does not exist."
fi

But when I executed the above script, it said "The SGID flag is not set on Hello.txt". And most users will get a similar output.

To enable SGID, you need to use the chmod command in the following manner:

chmod g+s Filename 

When I tried running it after using the chmod command over it, it gave me the following results:

15. The -u operator

The -u operator is used to check if the SUID (Set User ID) flag is set on a file or not.

When SUID is set, a user gets the temporary right to run a script of a file owner, not the user who is running the script.

For example, here, I tried to find if the Hello.txt has SUID set or not:

#!/bin/bash

filename="Hello.txt"

if [ -u "$filename" ]; then
  echo "The SUID flag is set on '$filename'."
else
  echo "The SUID flag is not set on '$filename'."
fi

But when I executed the above script, it said The SUID flag was not set on Hello.txt:

To set SGID on file, you can use the chmod command in the following manner:

chmod g+s filename

Once done, you can execute the script again:

16. The -k operator

The -k operator in bash is used to check if the file or the directory has a sticky bit set or not.

When you set a steaky bit on a file, it will be kept in cache memory for quicker access whereas if set on a directory, it restricts the write access.

When a file or a directory has a steaky bit set, it will show T at the end of the file permissions:

For example, here, I've used -k operator to find if the Hello.txt has a steaky bit set or not:

#!/bin/bash

filename="Hello.txt"

if [ -k "$filename" ]; then
  echo "The  sticky bit is set on '$filename'."
else
  echo "The  sticky bit is not set on '$filename'."
fi

When executed, it gave me the following output:

17. The -O operator

The -O operator in bash is used to find if the currently logged-in used is the owner of a specific file or not.

For example, here, I've used the -O operator to test if the Hello.txt is owned by the currently logged-in user or not:

#!/bin/bash

filename="Hello.txt"

if [ -O "$filename" ]; then
  echo "You are the owner of '$filename'."
else
  echo "You are not the owner of '$filename'."
fi

As I was the owner of the file, it gave me the following output:

18. The -G operator

The -G operator in bash is used to find if the group-id of the specified file is the same as yours (currently logged-in user).

For example, the following script will use the -G operator and find if the group ID of the currently logged-in user (identified using $USER) as same as the file:

#!/bin/bash

filename="Hello.txt"

if [ -G "$filename" ]; then
  echo "Group ID of a '$filename' is same as $USER."
else
  echo "Group ID of a '$filename' is not same as $USER."
fi

When executed, it gave me the following output:

19. The -N operator

The -N operator in bash is used to find if the file was modified since the last read.

Sounds confusing?

You may have files that can be accessed and modified by the other users. When you use the -N operator, it tells you if the file was modified since you last read it by someone in between.

For example, here, I used the following script to know if the file was modified since the last read:

#!/bin/bash

filename="Hello.txt"

if [ -N "$filename" ]; then
  echo "The file '$filename' has been modified since it was last read or written."
else
  echo "The file '$filename' has not been modified since it was last read or written."
fi

The other user abhiman was given the right to modify the file and he made some modifications to it so when I executed the above script, it gave me the following output:

20. The -nt operator

The -nt operator in Linux is used to find if one file is newer than the other.

For example, here, I took two files Hello.txt and LHB.txt and then used the -nt operator to check which one is newer than:

#!/bin/bash

file1="Hello.txt"
file2="LHB.txt"

if [ "$file1" -nt "$file2" ]; then
  echo "$file1 is newer than $file2."
else
  echo "$file1 is not newer than $file2."
fi

As the Hello.txt is older than the LHB.txt, it gave me the following output:

21. The -ot operator

The -ot operator in bash is used to compare two files and determine which one is older than the other.

Here, I will be using the same two files as I did earlier (Hello.txt and LHB.txt) and will compare them using the following script:

#!/bin/bash

file1="Hello.txt"
file2="LHB.txt"

if [ "$file1" -ot "$file2" ]; then
  echo "$file1 is older than $file2."
else
  echo "$file1 is not older than $file2."
fi

As the Hello.txt was created before the LHB.txt, it gave me the following:

22. The -ef operator

This one is interesting.

Using the -ef operator, you can verify if the two files are indicating the same data blocks.

In simple terms, you can verify if they are the hard links to the same file.

For example, I have created two hard links named HL-1 and HL-2 pointing to the same file to test if the -ef operator can verify them:

#!/bin/bash

file1="HL-1"
file2="HL-2"

if [ "$file1" -ef "$file2" ]; then
  echo "$file1 and $file2 point to the same file."
else
  echo "$file1 and $file2 do not point to the same file."
fi

As they both are hard links to the same file, it gave me the following output:

Did I miss any?

In this tutorial, I went through all the test operators available in the bash with examples of each explaining how you can use them.

Please let me know if I missed any.

Also, feel free to suggest what should I cover next.