Introduction to Bash Scripting

https://forge.uclouvain.be/barriat/learning-bash

November 05, 2026
CISM/CÉCI Training Sessions

Linux command line

A Linux terminal is where you enter Linux commands

It's called the Command Line User Interface

CLUI (or just CLI) is one of the many strengths of Linux :

  • allows to be independent of distros (or UNIX systems like OSX)
  • allows to easily work remotely (SSH)
  • allows to join together simple (and less simple) commands to do complex things and automate = scripting

In Linux, process automation relies heavily on scripting. This involves creating a file containing a series of commands that can be executed together.

2026-11-05 | Bash Scripting

Linux Shell

A shell is a program that takes commands from the keyboard and transmits them to the operating system to perform

The main function is to interpret your commands = language

Shells have some built-in commands

A shell also supports programming constructs, allowing complex commands to be built from smaller parts = scripts

Scripts can be saved as files to become new commands

many commands on a typical Linux system are scripts

2026-11-05 | Bash Scripting

Where does the shell sit?

a script is just a list of commands given to the shell instead of typed by you

2026-11-05 | Bash Scripting

Bash

The Bash shell is one of several shells available for Linux

It is the default command interpreter on most GNU/Linux systems. The name is an acronym for the "Bourne-Again SHell"

Bash Scripting Demo

#!/bin/bash

# declare STRING variable
STRING="Hello World"

# print variable on a screen
echo "$STRING"
2026-11-05 | Bash Scripting

Bash environment

In a Bash shell many things constitute your environment

  • the form of your 'prompt' (what comes left of your commands)
  • your home directory and your working directory
  • the name of your shell
  • functions that you have defined
  • etc.

Environment includes many variables that may have been set by bash or by you

2026-11-05 | Bash Scripting

Environment variables

Variables
USER the name of the logged-in user
HOME the user's home directory (similar to ~ )
PWD the current working directory
HOST the hostname of the current machine

Access the value of a variable by prefixing its name with $

So to get the value of USER you would use $USER in bash code

You can use special files to control bash variables : $HOME/.bashrc

2026-11-05 | Bash Scripting

Bash Scripting basics

By naming convention, bash scripts end with .sh

however, bash scripts can run perfectly fine without any extension

A good practice is to define a shebang : first line of the script
shebang is simply an absolute path to the shell interpreter

combination of sharp # (or hash) and bang !

The usual shebang for bash is #!/bin/bash

2026-11-05 | Bash Scripting

Comments start with #

On a line, any characters after # will be ignored (with the exception of #!)

echo "A comment will follow." # Comment here.
#                            ^ Note whitespace before #

There is no standard indentation

  • Pick a standard in your team that you can all work to
  • Use something your editor makes easy (e.g. 2 or 4 spaces)
2026-11-05 | Bash Scripting

Permissions and execution

  • Bash script is nothing else than a text file containing instructions to be executed sequentially

    by default in Linux, a new text file's permissions are -rw-r--r-- (or 644)

  • You can run the script hello_world.sh using
    • bash hello_world.sh
    • chmod u+x hello_world.sh then ./hello_world.sh

      after the chmod, your file is -rwxr--r-- (or 744)

2026-11-05 | Bash Scripting

Hands-on exercise

Your first bash script:

  1. create a folder bash_exercises and go there
  2. use your favourite editor (vim, obviously) to create a new file called exercise_1.sh
  3. write some code in it to display:

    The current directory is : /home/myself/bash_exercises
    You are myself, logged on lemaitre4

  4. make the file executable
  5. run it !

hints: $USER, $HOST

2026-11-05 | Bash Scripting

Variables and data types in Bash

Variables let you store data : numeric values or character(s)

You can use variables to read, access, and manipulate data throughout your script

You don't specify data types in Bash

  • assign directly : greeting="Welcome" or a=4
  • assign based on variable: b=$a

And then access using $: echo "$greeting"

!!! no space before or after = in the assignation !!!
myvar = "Hello World" 💥

2026-11-05 | Bash Scripting

Quotes for character(s) " '

Double will do variable substitution, single will not:

$ echo "my home is $HOME" 
my home is /home/myself
$ echo 'my home is $HOME'
my home is $HOME

Command Substitution

#!/bin/bash
# Save the output of a command into a variable
myvar=$( ls )
2026-11-05 | Bash Scripting

Always quote your variables

Without quotes, bash splits the value on spaces and expands *

file="my results.txt"
touch "$file"

ls $file      # ls: cannot access 'my': No such file or directory
              # ls: cannot access 'results.txt': No such file or directory
ls "$file"    # my results.txt

Rule of thumb: write "$var" (and "$(command)") unless you want the splitting

${var} (with braces) delimits the name: echo "${var}_backup"

2026-11-05 | Bash Scripting

Variable naming conventions

  • Variable names should start with a letter or an underscore

  • Variable names can contain letters, numbers, and underscores

  • Variable names should not contain spaces or special characters

  • Variable names are case-sensitive

  • Use descriptive names that reflect the purpose of the variable

  • Avoid using reserved keywords, such as if, then, else, fi, and so on...

  • Never name your private variables using only UPPERCASE characters to avoid conflicts with environment variables (PATH, HOME, USER...)

2026-11-05 | Bash Scripting

String manipulation

Consider filename=/var/log/messages.tar.gz

  • substring removal from left (# shortest match, ## longest match) :
    • ${filename#*/} is var/log/messages.tar.gz
    • ${filename##*/} is messages.tar.gz
  • substring removal from right (% shortest match, %% longest match) :
    • ${filename%.*} is /var/log/messages.tar
    • ${filename%%.*} is /var/log/messages

* matches any characters (like for file names)

How to return the length of a variable ? ${#filename} is 24

2026-11-05 | Bash Scripting

String manipulation : how it works

2026-11-05 | Bash Scripting

Arithmetic

Operator Operation
+ - * / addition, subtraction, multiplication, division
** power
% modulus (remainder after division)
var++ increase the variable var by 1
var-- decrease the variable var by 1
2026-11-05 | Bash Scripting

Arithmetic

Use double parentheses (❗ integers only ❗)

a=$(( 4 * 5 ))
b=$(( $a + 4 ))
echo $b # 24

# $ is optional inside parentheses

b=$(( a - 3 ))
echo $b # 17

(( b++ ))
(( b += 3 ))
echo $b # 21
2026-11-05 | Bash Scripting

Conditional statements

Use:

  • if condition; then to start conditional block
  • elif condition; then to start alternative condition block
  • else to start alternative block
  • fi to close conditional block

The following operators can be used between conditions:

  • || means OR
  • && means AND
2026-11-05 | Bash Scripting

Conditional syntax

if [[ $num -gt 5 && $num -le 7 ]]; then

  echo "$num is 6 or 7"

elif [[ $num -lt 0 || $num -eq 0 ]]; then

  echo "$num is negative or zero"

else
  echo "$num is positive (but not 6, 7 or zero)"
fi

[[ ... ]] is the bash test command. You may also meet [ ... ] (the older, POSIX test): it is more fragile, prefer [[ ]] in bash scripts

2026-11-05 | Bash Scripting

Conditions with numbers

Operator Description
! EXPRESSION The EXPRESSION is false
INT1 -eq INT2 INTEGER1 is equal to INTEGER2
INT1 -ne INT2 INTEGER1 is different from INTEGER2
INT1 -gt/-ge INT2 INTEGER1 is higher / higher or equal to INTEGER2
INT1 -lt/-le INT2 INTEGER1 is lower / lower or equal to INTEGER2

Note: inside [[ ]], the signs == < > compare strings ([[ 10 < 9 ]] is true !)
Inside (( )) they compare numbers (see next slides)

2026-11-05 | Bash Scripting

Conditions with strings

Operator Description
-n STRING The length of STRING is greater than zero
-z STRING The length of STRING is zero (ie it is empty)
STR1 == STR2 STR1 is equal to STR2 (also =)
STR1 != STR2 STR1 is not equal to STR2
STR == PATTERN STR matches a glob. pattern, e.g. [[ $f == *.txt ]]
STR =~ REGEX STR matches a reg. expression, e.g. [[ $n =~ ^[0-9]+$ ]]
2026-11-05 | Bash Scripting

Conditions on files

Operator Description
-e FILE FILE exists
-f FILE FILE exists and is a regular file
-d FILE FILE exists and is a directory
-s FILE FILE exists and is not empty
-r/-w/-x FILE FILE exists and user has read/write/execute permissions
if [[ -e "my_file.sh" ]]; then
  echo "my_file.sh exists"
fi
2026-11-05 | Bash Scripting

Conditional with arithmetics

If your condition is only arithmetics / booleans you can use double parentheses (just like we did for variables) :

if (( num % 2 == 0 )); then
  echo "$num is an even number !"
fi

if (( num % 2 == 0 && num % 3 == 0 )); then
  echo "$num can be divided by 2 and 3"
fi

Inside (( )), use the usual signs: == != < <= > >=

2026-11-05 | Bash Scripting

Conditional Summary Table

2026-11-05 | Bash Scripting

Reading user input

read stores what the user types into a variable

#!/bin/bash
read -p "Enter your name: " name
echo "Hello $name"
  • -p "text" : display a prompt
  • -r : keep backslashes as they are (always a good idea)
  • read a b : first word in a, the rest in b
2026-11-05 | Bash Scripting

Case Statements

Compare one value against several patterns

#!/bin/bash
read -p "Continue? [y/n] " answer
case $answer in
  y|Y|yes)
    echo "Let's go"
    ;;
  n|N|no)
    echo "Bye"
    ;;
  *)
    echo "Please answer y or n"
    ;;
esac

each block ends with ;; and *) catches everything else

2026-11-05 | Bash Scripting

Hands-on exercise

  1. In your bash_exercises folder create exercise_2.sh and make it executable
  2. Ask the user for a number with read -p and put it in a variable number
  3. Check that the number is smaller than 100, otherwise tell the user
  4. Tell the user whether the number is even or odd
  5. Bonus : check that the answer is a number, otherwise tell the user

    [[ $number =~ ^[0-9]+$ ]] is true when number contains only digits

2026-11-05 | Bash Scripting

Loops

Useful for automating repetitive tasks

Basic loop structures in Bash scripting :

  • while : perform a set of commands while a test is true

  • for : perform a set of commands for each item in a list

  • controlling loops

    • break : exit the currently running loop
    • continue : stop this iteration of the loop and begin the next iteration
2026-11-05 | Bash Scripting

Examples

#!/bin/bash

# Basic while loop
counter=0
while (( counter < 3 )); do
  echo "$counter"
  (( counter++ ))
done
# range
for i in {1..5}; do
  echo "i = $i"
done

{1..$n} does not work with a variable: use for (( i=1; i<=n; i++ ))

2026-11-05 | Bash Scripting
# list of strings (split on spaces)
words='Hello great world'
for word in $words; do echo "$word"; done
# range with steps
for value in {10..0..2}; do echo "$value"; done
# set of files (glob)
for file in "$path"/*.f90; do echo "Compiling $file"; done
# command result (split on spaces, NOT on lines!)
for user in $( cut -d: -f1 /etc/passwd ); do echo "$user"; done

to read a file line by line, use while read (see later)

2026-11-05 | Bash Scripting

Arrays

Indexed arrays

# Declare an array with 4 elements
my_array=( 'Debian Linux' 'Redhat Linux' Ubuntu OpenSUSE )
# get number of elements in the array
echo "Number of elements: ${#my_array[@]}"   # 4
# get one element (index starts at 0)
echo "${my_array[1]}"                        # Redhat Linux
# add an element at the end
my_array+=( Fedora )
# echo array's content
echo "${my_array[@]}"
2026-11-05 | Bash Scripting

Loop over an array: quote it!

my_array=( 'Debian Linux' 'Redhat Linux' Ubuntu )

for distro in ${my_array[@]}; do echo "$distro"; done
# Debian
# Linux
# Redhat
# Linux
# Ubuntu

for distro in "${my_array[@]}"; do echo "$distro"; done
# Debian Linux
# Redhat Linux
# Ubuntu

"${my_array[@]}" keeps each element as one word

2026-11-05 | Bash Scripting

Hands-on exercise

  1. In your bash_exercises folder create a new bash file called exercise_3.sh and make it executable
  2. Use the following list of words and put them together in an array:
    misplace discipline birthday lie classroom swallow casualty failure partner visible
  3. Register the start time with date +%s%N (nanoseconds since 1970) in a variable tstart
  4. Loop over the words and display the number of letters of each word (${#word})
  5. Compute the total number of letters and find the longest word
  6. Register the end time in tend, then display the run time (in µs), the total and the longest word

also try time ./exercise_3.sh

2026-11-05 | Bash Scripting

Arguments - Positional Parameters

How to pass command-line arguments to a bash script ?

#!/bin/bash
echo $1 $2 $4
echo $0
echo $#
echo "$@"
bash test_arg.sh a b c d e
a b d
test_arg.sh
5
a b c d e
2026-11-05 | Bash Scripting
Special Variables
$0 the name of the script
$1 ... $9, ${10} the arguments (use braces from 10 on)
$# how many arguments were passed
"$@" all the arguments, each one kept as a separate word
$* all the arguments, joined into a single string
$$ the process ID of the current script
$? the exit status of the most recently run process

shift drops $1 and moves the others one place to the left ($2 becomes $1...)

2026-11-05 | Bash Scripting

Flags

#!/bin/bash
while getopts u:a:f: flag
do
    case "${flag}" in
        u) username=${OPTARG};;
        a) age=${OPTARG};;
        f) fullname=${OPTARG};;
    esac
done
echo "Username: $username"
echo "Age: $age"
echo "Full Name: $fullname"
bash test_arg.sh -f 'John Smith' -a 25 -u john

u: means "option -u expects a value", stored in $OPTARG

2026-11-05 | Bash Scripting

Input/Output streams

Every command is started with 3 standard I/O streams (file descriptors)

fd Name Default
0 stdin : standard input, provides input to commands keyboard
1 stdout : standard output, displays output from commands terminal
2 stderr : standard error, displays error output from commands terminal

Shell has several meta-characters and control operators to connect these streams to files or to other commands

2026-11-05 | Bash Scripting

Input/Output streams

2026-11-05 | Bash Scripting

Control operators

Character Effect
; Normal separator between commands
&& Execute next command only if command succeeds
|| Execute next command only if command fails
& Run the command in the background: don't wait for it before starting the next command
| Pipe: use output of command as input for the next command
2026-11-05 | Bash Scripting

Pipes

Chain small commands: the stdout of each one becomes the stdin of the next

# the 5 most used commands in your history
history | awk '{print $2}' | sort | uniq -c | sort -rn | head -5

# how many lines contain "ERROR" in all log files
cat *.log | grep ERROR | wc -l

only stdout goes through the pipe, stderr still goes to the terminal

2026-11-05 | Bash Scripting

Redirections

Syntax Effect
cmd > file Send stdout of cmd to file (overwrite)
cmd >> file Same but in append mode
cmd 2> file Send stderr of cmd to file
cmd > file 2>&1 Send stdout and stderr to file (also &> file)
cmd < file Use content of file as stdin of cmd
cmd > /dev/null Throw the output away

⚠️ order matters: cmd 2>&1 > file sends only stdout to file

2026-11-05 | Bash Scripting

Redirections and pipes

2026-11-05 | Bash Scripting

Command separators

Commands can be combined using meta-characters and control operators

# cmd1; cmd2
$ cd myfolder; ls   # no matter cd to myfolder successfully, run ls

# cmd1 && cmd2
$ cd myfolder && ls  # run ls only after cd to myfolder

# cmd1 || cmd2
$ cd myfolder || ls  # if failed cd to myfolder, `ls` will run
2026-11-05 | Bash Scripting

Redirections in practice

From bash script

#!/bin/bash
# write a message on STDERR
echo "Error: file not found" >&2

Output streams to file(s)

./my_script.sh > STDOUT.log 2> STDERR.err
2026-11-05 | Bash Scripting

Here documents: multi-line input

Everything between <<EOF and EOF is sent to the stdin of the command (variables are replaced)

Very handy to write a file from a script, e.g. a Slurm job script:

cat > job.slurm <<EOF
#!/bin/bash
#SBATCH --time=01:00:00
echo "Running as $USER"
EOF
2026-11-05 | Bash Scripting

Return codes

Linux command returns a status when it terminates normally or abnormally

  • every Linux command has an exit status
  • the exit status is an integer number
  • a command which exits with a 0 status has succeeded
  • a non-zero (1-255) exit status indicates failure

How do I display the exit status of shell command ?

date
echo $?
2026-11-05 | Bash Scripting

How to store the exit status of the command in a shell variable ?

#!/bin/bash
date
status=$?
echo "The date command exit status : ${status}"

if directly tests the exit status of a command

if grep -q "ERROR" run.log; then
  echo "run.log contains errors"
fi
2026-11-05 | Bash Scripting

&& and || with exit codes

2026-11-05 | Bash Scripting

Functions

  • "small script within a script" that you may call multiple times
  • great way to reuse code
  • a function is most reusable when it performs a single task
#!/bin/bash
hello_world () {
   echo 'hello, world'
}
hello_world

Functions must be defined before they are called

defining a function doesn't execute it

2026-11-05 | Bash Scripting

Variables Scope

# Define bash global variable
# This variable is global and can be used anywhere in this bash script
var="global variable"

my_function () {
  echo "$var"
  # Define my_function local variable
  # This variable is local to my_function only
  local var="local variable"
  echo "$var"
}

echo "$var"
my_function
# Note the bash global variable did not change
# "local" is a bash builtin, usable only inside functions
echo "$var"
2026-11-05 | Bash Scripting

Return Values

Bash functions don't return a value like in other languages

After completion, the status of a function (0-255) is the one of its last command, or the one given to return :

is_even () {
  (( $1 % 2 == 0 ))   # status 0 if true, 1 if false
}
if is_even 4; then echo "4 is even"; fi

my_function () {
  return 55
}
my_function
echo $?   # 55
2026-11-05 | Bash Scripting

Return an arbitrary value from a function

echo the result and capture it with a command substitution

my_function () {
  local func_result="some result"
  echo "$func_result"
}
func_result="$(my_function)"
echo "$func_result"
2026-11-05 | Bash Scripting

Passing Arguments

As for a bash script: see above ($1, "$@", $#, etc)

#!/bin/bash
print_something () {
    echo "Hello $1"
}
print_something Mars

❗ Although it is possible, you should try to avoid having functions using the name of existing linux commands.

2026-11-05 | Bash Scripting

Hands-on exercise

  1. Create exercise_4.sh, which takes words as arguments

    ./exercise_4.sh misplace lie classroom

  2. If no word is given, print a usage message on stderr and exit 1
  3. Write a function count_letters WORD which echoes the number of letters of WORD
  4. Write a function is_long WORD which returns 0 if WORD has more than 7 letters, 1 otherwise
  5. Loop over the arguments ("$@") and use your 2 functions to display:

    misplace : 8 letters (long)
    lie : 3 letters (short)

  6. Bonus : exit 2 if none of the words is long, and check it with echo $?
2026-11-05 | Bash Scripting

Subshells

  • A subshell is a "child shell" spawned by the main shell ("parent shell")
  • A subshell is a separate instance of the command process, run as a new process
  • Unlike executing a shell script (see next slides), subshells inherit all the variables of the original process
  • A subshell allows you to execute commands within a separate shell environment = Subshell Sandboxing

    useful to set temporary variables or change directories without affecting the parent shell's environment

  • Subshells can be used for parallel processing
2026-11-05 | Bash Scripting

Syntax

A command list embedded between parentheses runs as a subshell :

#!/bin/bash
( cd /tmp ; myvar=42 ; ls )
pwd          # still in the original folder
echo $myvar  # empty

Reminder : variables in a subshell are not visible outside the block of code in the subshell

2026-11-05 | Bash Scripting

Shell vs Environment Variables

Consider the script test.sh below :

#!/bin/bash
echo "var1 = ${var1}"
echo "var2 = ${var2}"

Then do the following commands :

var1=23
export var2=12
bash test.sh

By default, variables from the main interpreter are not available in scripts, unless you export them.

2026-11-05 | Bash Scripting

Differences between Sourcing and Executing a script

  • source a script = execution in the current shell
  • execute a script = execution in a new shell (a child process of the current shell)

Source a script using source or .

source test.sh
. test.sh

official (POSIX) one is . : source is a bash builtin doing exactly the same

2026-11-05 | Bash Scripting

Example

#!/bin/bash
# test.sh
country="Belgium"
greeting() {
    echo "You're in $1"
}
greeting "$country"

In your terminal: set country="France", run ./test.sh or source test.sh, then:

echo "$country"
greeting "$country"
2026-11-05 | Bash Scripting

Execute, source or subshell?

2026-11-05 | Bash Scripting

Debug

Tips and techniques for debugging and troubleshooting Bash scripts

use shellcheck

A static analysis tool which finds the classical bugs (missing quotes, wrong tests...) before running the script

$ shellcheck exercise_4.sh
In exercise_4.sh line 22:
for word in $@; do
            ^-- SC2068: Double quote array expansions to avoid re-splitting elements.

also available online: https://www.shellcheck.net

2026-11-05 | Bash Scripting

use set -x (or bash -x script.sh)

enables debugging mode : print each command that it executes to the terminal, preceded by a +

$ bash -x exercise_2.sh
+ read -p 'First number: ' number1
First number: 12
+ ((  number1 < 100  ))
+ echo 'number1 is smaller than 100'
number1 is smaller than 100

set -x ... set +x to debug only a part of the script

2026-11-05 | Bash Scripting

check the exit code

#!/bin/bash
cp input.dat /scratch/
if [[ $? -ne 0 ]]; then
    echo "Error occurred" >&2
fi

use echo

Classical but useful technique : insert echo throughout your code to check variable content

#!/bin/bash
echo "Value of variable x is: $x"
2026-11-05 | Bash Scripting

use set -euo pipefail

Option Effect
set -e exit the script as soon as a command fails
set -u an unset variable is an error (catches typos like $nmae)
set -o pipefail a pipe fails if any of its commands fails (not only the last one)

⚠️ set -e is ignored in some places (inside if conditions, before && / ||...): it is a safety net, not a replacement for real error checks

2026-11-05 | Bash Scripting

Thank you for your attention

2026-11-05 | Bash Scripting

Bonus: running parallel processes in subshells

Processes may execute in parallel within different subshells

permits breaking a complex task into subcomponents processed concurrently

Example : job.sh

#!/bin/bash
job() {
  local job_id=$1
  local i=0
  while (( i < 10 )); do
    echo "${i}: job $job_id"
    (( i++ ))
    sleep 0.2
  done
}

sequential processing (manager_seq.sh) or parallel processing (manager_par.sh)

2026-11-05 | Bash Scripting

Bonus: running parallel processes in subshells

#!/bin/bash
# manager_seq.sh
source job.sh
echo "start"
for job_id in {1..2}; do job "$job_id" ; done
echo "done"
#!/bin/bash
# manager_par.sh
source job.sh
echo "start"
for job_id in {1..2}; do job "$job_id" & done
wait # Don't execute the next command until subshells finish.
echo "done"
time ./manager_seq.sh
time ./manager_par.sh

for many tasks, see also xargs -P, GNU parallel and, on the CÉCI clusters, Slurm job arrays

2026-11-05 | Bash Scripting

Bonus: sequential vs parallel

job & starts each job in a background subshell, wait waits for all of them

2026-11-05 | Bash Scripting

Durée max: 10-15 min

## String manipulation Consider `string=abcABC123ABCabc` * string length : `${#string}` is `15` * substring extraction : * `${string:7}` is `23ABCabc` * `${string:7:3}` is `23A` * `${string:(-4)}` or `${string: -4}` is `Cabc` ---

JDF: a mon avis pas utile - `let` make a variable equal to an expression ```bash #!/bin/bash let a=5+4 echo $a # 9 let a++ let "a = 4 * $a" ``` - `expr` : print out the result of the expression ```bash #!/bin/bash expr 5 + 4 # 9 expr 5+4 # boom expr "5 + 4" # boom a=$( expr 10 - 3 ) ``` - double parentheses : return the result of the expression > it is the **preferred method** ---

--- ### Associative arrays = Dictionaries (Bash 4.0 or higher) By default, a bash array is an indexed array : need to use the `declare` command ```bash declare -A acronyms # -A for associative array acronyms[ACK]=Acknowledgement acronyms[EOF]="End of Frame" echo ${acronyms[ACK]} if [ ${acronyms[EOF]+_} ]; then echo "Found"; else echo "Not found"; fi ``` > the variable expansion `${MYVAR+ABC}` expands to `ABC` is `MYVAR` is set and to nothing otherwise ```bash declare -A countries=( [ALB]=Albania [BHR]=Bahrain [CMR]=Cameroon [DNK]=Denmark [EGY]=Egypt ) echo ${countries[@]} echo ${!countries[@]} countries+=( [FJI]=Fiji ) echo ${countries[@]} unset countries[BHR] echo ${countries[@]} ``` <!-- ### About `declare` ```bash declare --help ``` Examples : - declare a variable without a value - force a variable to be an integer only - declare a variable as a **parameter** (read-only) - force a character(s) variable to store all uppercase or lowercase letters - display the attributes and values of all variables - etc.

![bg right 85%](./assets/select_example.png) --- ```bash #!/bin/bash # How to iterate over keys or values of an Array declare -A fruits fruits[south]="Banana" fruits[north]="Orange" fruits[west]="Passion Fruit" fruits[east]="Pineapple" for key in "${!fruits[@]}" do echo "Key is '$key' => Value is '${fruits[$key]}'" done ```