Black Friday 2025 – NPI EA (cat = Baeldung on Linux)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

Baeldung Pro – Linux – NPI EA (cat = Baeldung on Linux)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

Partner – Orkes – NPI EA (tag=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Overview

Printing the exact commands in a script before execution can be really useful. In this tutorial, we’ll learn how to make Bash scripts echo commands before they’re executed.

2. The set -x or set -o xtrace Option

The set -x option is one of the methods we can use to see what’s going on in Bash scripts. Let’s now see some ways we can use this option.

2.1. Adding set -x to a Script

When we add set -x inside scripts,  it echoes any command that comes after set-x. Also, the set -x option expands variables. We can turn off the effect of this option using set +x:

#!/bin/bash

echo "file operation begins..."

set -x
mkdir new_directory
cd new_directory
touch data.txt
ls $PWD
set +x

echo "finished!" 

Let’s run the script:

$ ./example_1.sh

file operation begins...
+ mkdir new_directory
+ cd new_directory
+ touch data.txt
+ ls /new_directory
data.txt
+ set +x
finished!

Here, we add set -x before some commands. The shell prints these commands with a + sign before their actual execution.

Also, as we can see in the output, set -x expands the $PWD variable to /new_directory. Then we turned off the feature using set +x.

2.2. Using -x in a Shebang Line

When we add -x to the shebang line of a script, it echoes each command before execution. With this, we have a full view of commands a script executes:

$ cat example_2.sh

#!/bin/bash -x

name="John"
age=25

echo "Name: $name"
echo "Age: $age"

if [ "$age" -ge 18 ]; then
    echo "You're an adult."
else
    echo "You're not an adult."
fi

echo "Script execution complete."

The script produces the output:

$ ./example_2.sh

+ name=John
+ age=25
+ echo 'Name: John'
Name: John
+ echo 'Age: 25'
Age: 25
+ '[' 25 -ge 18 ']'
+ echo 'You're an adult.'
You're an adult.
+ echo 'Script execution complete.'
Script execution complete.

Also, we can use set +x to stop printing the commands.

2.3. Running Scripts Using bash -x

Let’s say we don’t want to edit a script. Using bash -x, we can still enable command echoing directly from the command line:

$ cat example_3.sh

#!/bin/bash

greet() {
    echo "Hello, $1!"
}

user="Bob"

greet "$user"

date

ls

uptime

echo "Script execution complete!"

Let’s run the script:

$ bash -x example_3.sh

+ user=Bob
+ greet Bob
+ echo 'Hello, Bob!'
Hello, Bob!
+ date
Mon Apr  1 07:36:15 UTC 2024
+ ls
data.txt  new_directory  new_script.sh	processed  website_status.txt
+ uptime
 07:36:15 up  2:40,  0 users,  load average: 0.31, 0.43, 0.48
+ echo 'Script execution complete!'
Script execution complete!

The bash -x command prints every command in the script, even though -x isn’t set within the script.

3. The set -v or set -o verbose Option

The set -v option does the same thing as set -x. But, unlike set -x, it doesn’t print a + sign before the command. Also, it doesn’t expand the variables like we saw in the previous option.

3.1. Enabling set -v Within a Script

We can enable set -v within a specific section of the script to help us debug better. Also, set +v disables verbose output:

$ cat example_4.sh

#!/bin/bash

echo "This message will be printed."
set -v
echo "This line will be shown before it runs."
ls
set +v
echo "This message will be printed normally."

Let’s run the script:

$ ./example_4.sh

This message will be printed.
echo "This line will be shown before it runs."
This line will be shown before it runs.
ls
data.txt  new_directory  new_script.sh	processed  website_status.txt
set +v
This message will be printed normally.

The set -v command within the script echoes every command that comes after it. So, it prints the next lines before execution. Also, the set +v command stops the printing of commands.

3.2. Using -v in a Shebang Line

When we add -v to the shebang line at the top of a Bash script, it prints every command in the script before execution:

$ cat example_5.sh

#!/bin/bash -v

echo "Checking for updates..."
sudo apt update

echo "Installing new packages..."
sudo apt upgrade -y

echo "Script complete!"

We get something similar to the output below after running the script:

./example_5.sh

#!/bin/bash -v

echo "Checking for updates..."
Checking for updates...
sudo apt update
...

echo "Installing new packages..."
Installing new packages...
sudo apt upgrade -y
...

echo "Script complete!"
Script complete!

The shebang line #!/bin/bash -v tells Bash to print every command in it. So, the script prints each line before execution.

3.3. Running Scripts Using bash -v

We can make a script to print every command without editing the script itself. The script can print commands using bash -v directly on the command line:

$ cat example_6.py

#!/bin/bash

echo "Starting file operations..."
mkdir new_directory
cd new_directory
touch example_file.txt
ls
echo "File operations complete!"

Let’s find out what the script produces:

$ bash -v example_6.sh

#!/bin/bash

echo "Starting file operations..."
Starting file operations...
mkdir new_directory
cd new_directory
touch example_file.txt
ls
example_file.txt
echo "File operations complete!"
File operations complete!

The example above tells us that the script prints each command before execution.

4. Custom echo Function

Let’s create a custom echo function that prints each command before its execution. It can be pretty helpful when we want to have more control over what’s printed:

$ cat example_7.sh

#!/bin/bash

echo_cmd() {
    echo "Executing: $@"
    "$@"
}

echo_cmd echo Hello, World!
echo_cmd ls -l
echo_cmd pwd

When we run the command above, we’ll get:

./example_7.sh

Executing: echo Hello, World!
Hello, World!
Executing: ls -l
total 28
-rw-r--r-- 1 root root     0 Apr  1 06:31 data.txt
drwxr-xr-x 2 root root  4096 Apr  1 13:25 new_directory
-rwxr-xr-x 1 root root   113 Apr  2 08:47 new_script.sh
drwxr-xr-x 2 root root  4096 Apr  1 05:57 processed
-rw-r--r-- 1 root root 15757 Apr  1 06:50 website_status.txt
Executing: pwd
/new_directory

The custom echo function starts by printing, “Executing: ” followed by the entire command line it receives, before executing it.

5. Conclusion

In this article, we learned about the set -x, set -v, and a custom echo function. We saw how they help print commands in Bash scripts during execution.

With this understanding, we have a useful tool that can help us debug issues in Bash scripts.

1 Comment
Oldest
Newest
Inline Feedbacks
View all comments