Writing shell scripts
Last modified on Fri 22 Jul 2022

What are shell scripts?

Shell scripts are programs consisting of a series of commands in a file.

Instead of typing various commands into the Terminal one by one, you can execute them all by running the script.

With a shell script you can automate repetitive tasks to do them easily and more accurately.

Read Using Terminal for more details on shell and the Terminal.

bash or zsh

bash is the default shell for many Linux distributions and was also the default command-line interpreter for Mac on macOS Mojave and earlier versions.

Newer versions of macOS (Catalina and later) use zsh as the default shell.

zsh is an extended version of sh and includes some bash features. Most commands, control structures and syntax from bash work in zsh as well.

Install zsh

Install zsh using Homebrew: brew install zsh

You can also install oh-my-zsh, a framework for managing zsh configuration. It offers built-in plugins and themes to make your work in the terminal more interesting and easier.

Check the path to the zsh binary

Once you have zsh installed, check the path to the binary by running:

which zsh

Output: /usr/bin/zsh

You will use this path in the first line of your shell script. The first line must set the path to the shell interpreter that you want to run the script with.

Set up zsh as default

If you are switching to zsh, you probably also want to set it up as default.

  1. Make zsh default: chsh -s $(which zsh)

    • You might need to log out and then log back in for the changes to take effect
  2. Check that the zsh is now the default: echo $SHELL

    • Expected output: /bin/zsh
  3. Check the zsh version: $SHELL --version

    • Expected output: zsh 5.8

For more information check out the zsh documentation.

Writing a zsh script

Create a new file

Start working on your script by creating a new file by using a text editor.

Or using a command-line interface: touch script_name.zsh

The extension for bash scripts is .sh. The same extension can be used for the zsh scripts as well. The extension is not necessary but will help you identify the file more easily. You can also change the file extension for your zsh scripts from .sh to .zsh.

The file extension has no effect on the interpreter used for executing the script. The interpreter is determined by the shebang.


The first line of a shell script is the so-called shebang character sequence. This line indicates which interpreter to use when running the script.


The shebang consists of the following sequence:

Adding comments

You are encouraged to use comments in your scripts. The comments start with the # character and will not be executed. They will, however, help with the code readability.

# Say “Hello” to the world

Adding code

Once you have the shebang and the comment in place, add some code to be executed. For starters, say “Hello” to the world when the script is executed.

The command used for printing the string: echo

# Say “Hello” to the world

echo Hello world!

Executing a ZSH script

Execute the script by providing the full file path to the script. When running the script, the first argument specifies the interpreter you want to use. For example, if the file is in the Documents folder, run the following command to execute the script using zsh:

zsh Documents/script_name.zsh

Executing a script that accepts arguments:

zsh Documents/script_name.zsh <arg1> <arg2> <argN>

Execute the script by providing a relative path to the script:

zsh ./script_name.zsh <arg1> <arg2> <argN>

Permission denied

If you run your script and get the zsh: permission denied error, you will need to modify the file permissions. The permission can be updated for the file or the entire folder. To set execute permissions for the shell script, use the chmod command:

chmod +x script_name.zsh

Adding variables to the script

Define a variable:


To get the value of the variable, add the $ character before the variable name:


# Say “Hello” to John


echo $greeting $name

Adding parameters (flags) to the script

You can add parameters (flags) to the script to modify its behaviour by passing arguments. This is done using the built-in shell command for parsing command-line arguments getopts.

The getopts command is added inside a while loop so that all options are parsed. Right after the getopts keyword, we define the options our script accepts. In this case, the options are name (n) and age (a). The OPTARG refers to the corresponding value passed to the script.

# Say “Hello” to the user


while getopts n:a: flag
    case "${flag}" in
        n) name=${OPTARG}
        echo "Name set to: $name";;
        a) age=${OPTARG}
        echo "Age set to: $age";;

echo "$greeting $name ($age)"

Executing the script

The script is executed by providing the interpreter, path to the script and then the arguments. The arguments are provided by specifying the argument starting with a hyphen (e.g. -n) and then its value, separated with a single space.

zsh ./test_input.zsh -n John -a 25


Name set to: John
Age set to: 25
Hello John (25)

Additional resources

bash cheatsheet

zsh cheatsheet

Command line arguments in scripts

Positional parameters in scripts

Using flag arguments