1. Introduction

Shell scripting is one of the most helpful features of the Linux operating system. We can use shell scripts to perform various operations, such as installing software, fixing bugs, etc.

If we want to write quality shell scripts in Bash, formatting them properly is necessary. This way, we’ll be able to improve two things:

  • Make the code more readable
  • Increase the efficiency of the debugging process

In this tutorial, we’ll see some commands that will show us how to properly format the source of a shell script.

2. The shfmt Command

shfmt is a useful tool for formatting, parsing, and interpreting our shell scripts. Since the shfmt command allows us to format our scripts how we want, we consider it a highly customizable tool.

But before we use shfmt, we’ve got to install it on our machine, as it’s not an inbuilt tool.

For Ubuntu:

$ sudo snap install shfmt

In Alpine Linux:

$ sudo apk add shfmt

For Arch Linux / EndeavourOS / Manjaro Linux:

$ sudo pacman -S shfmt

Once the installation is complete, we’re eligible to use shfmt to format our shell scripts. But first, let’s create a simple shell script (file.sh) in Bash:

        #!/bin/bash

function        f1(){
            echo "This is Baeldung."
            }

f1

In this shell script, we declare a function that prints the given string to the screen when called.

As we can see above, the shell script is clearly in an unformatted state.

Now, let’s type shfmt in the terminal:

$ shfmt file.sh

The filename after the shfmt command indicates the shell script we want to format.

Let’s check the output:

#!/bin/bash

function f1() {
        echo "This is Baeldung."
}

f1

Evidently, the above output indicates that the shell script is well-indented and well-formatted.

3. The shfmt -i Command

If we carefully look at the formatted script, we’ll notice that the indentation is 8 spaces by default.

If we want to customize this setting and set our own indentation rule, we can use the -i option, short for –indent, with the shfmt command:

$ shfmt -i 4 file.sh

The number that we used after the -i option indicates the number of spaces that we want to use for indentation.

Now, let’s check what the output is:

#!/bin/bash

function f1() {
    echo "This is Baeldung."
}

f1

Clearly, the indentation is performed with the help of 4 spaces.

4. The shfmt -d Command

If we want to see the changes between the unformatted and the formatted script, we can use the -d option, short for –diff, with the shfmt command:

$ shfmt -d file.sh

Let’s have a look at the output:

--- file.sh.orig
+++ file.sh
@@ -1,7 +1,7 @@
 #!/bin/bash

-function        f1(){
-           echo "This is Baeldung."
-           }
+function f1() {
+    echo "This is Baeldung."
+}

 f1

Let’s break it down step by step:

  • In the first line, the “—” symbol and the .orig extension indicate the unmodified version of the file.
  • In the second line, the “+++” symbol indicates the modified version of the file.
  • The third line states that the unmodified file (-) and the modified file (+) have lines 1-7 in the output.

Next, the changes between those two files are shown on the screen. Now, if we carefully take a look, we’ll notice that each line either has no symbol or has a specific symbol at the beginning.

Let’s see what the lines indicate through their symbolic nature:

  • The lines that don’t contain a symbol indicate that they’re present in both files.
  • Those starting with “-” suggest that they only existed in the unmodified version.
  • Those starting with “+” suggest that they only exist in the modified version.

Evidently, this command allows us to have a detailed view of the modifications performed by shfmt.

5. The shfmt -l Command

If we want to list all the files that need formatting, we can append the -l option, short for –list, to the shfmt command.

So, we’re aware of the fact that the file.sh shell script is well-formatted. Hence, this file won’t appear in the list of unformatted files.

So, let’s now create two more shell scripts (file2.sh and file3.sh) that will contain the same code as file.sh, except these ones will be in an unformatted state.

Firstly, we’ll create file2.sh:

    #!/bin/bash

function        f1(){
            echo "This is Baeldung."
                    }

f1

Secondly, we’ll create file3.sh:

            #!/bin/bash

function    f1(){
                echo "This is Baeldung."
                }

f1

Now, we’ll type the following command in the terminal:

$ shfmt -l file*.sh

We used the file*.sh string after the -l option because we wanted to select all the unformatted files whose names start with file and contain any number of letters afterward (indicated by “*”).

Let’s now check the output:

file2.sh
file3.sh

As expected, the unformatted shell scripts file2.sh and file3.sh are listed in the output.

6. The shfmt -w Command

When we format a file using the shfmt command, it prints the output to the terminal. If we want it to print it to the file instead, we can use the -w option, short for –write, with shfmt:

$ shfmt -w file.sh

Let’s now check what file.sh contains:

#!/bin/bash

function f1() {
        echo "This is Baeldung."
}

f1

Evidently, we’ve succeeded in printing the formatted code to the file itself.

7. Conclusion

In this tutorial, we’ve gone through a series of commands that will help us properly format our shell scripts and perform other formatting-related things.

In summary, if we succeed in keeping our shell scripts well-formatted, they can be incredibly useful in numerous situations.