Passa al contenuto principale

Bash Scripting

Download some example scripts
note

You can download some example scripts that are used here:

wget https://linux-cli.fs.al/apps/part1.tgz
tar xfz part1.tgz
cd part1/ && ls

1. Hello world

  • nano hello.sh :

    #!/bin/bash

    echo "Hello World!"
    echo "How are you today?"
    chmod +x hello.sh
    ./hello.sh
  • nano hello.sh :

    #!/bin/bash

    echo "
    Hello World!
    How are you today?
    "
  • nano hello.sh :

    #!/bin/bash

    cat <<EOF
    Hello World!
    How are you today?
    EOF

2. Loops: for, while, until

  • nano count.sh:

    #!/bin/bash

    for i in {1..5}; do
    echo $i
    done
    echo "Finished."

    Replace {1..5} with 1 2 3 4 5, then with a b c d e.

  • nano count.sh:

    #!/bin/bash

    for ((i=1; i<=5; ++i)); do
    echo $i
    done
    echo 'Finished.'
  • nano count.sh:

    #!/bin/bash

    count=1
    while ((count <= 5)); do
    echo $count
    count=$((count + 1))
    done
    echo "Finished."
  • nano count.sh:

    #!/bin/bash

    count=1
    while [[ $count -le 5 ]]; do
    echo $count
    count=$((count + 1))
    done
    echo "Finished."
  • nano count.sh:

    #!/bin/bash

    count=1
    until [[ $count -gt 5 ]]; do
    echo $count
    count=$((count + 1))
    done
    echo "Finished."

3. Branching with if

  • nano modulo.sh:

    #!/bin/bash

    for ((i = 0; i <= 20; ++i)); do
    if ((i % 5 == 0)); then
    printf "<%d> " "$i"
    else
    printf "%d " "$i"
    fi
    done
    printf "\n"
  • nano modulo.sh:

    #!/bin/bash

    for ((i = 0; i <= 20; ++i)); do
    if ((i % 5 == 0)); then
    printf "<%d> " "$i"
    elif ((i % 3 == 0)); then
    printf "[%d] " "$i"
    else
    printf "%d " "$i"
    fi
    done
    printf "\n"

4. Read input

  • Testing integers:

    test-int-1.sh
    #!/bin/bash

    echo -n "Please enter an integer -> "
    read int

    if [[ ! $int =~ ^-?[0-9]+$ ]]; then
    echo "Input value is not an integer." >&2
    exit 1
    fi

    if ((int == 0)); then
    echo "$int is zero."
    else
    if ((int < 0)); then
    echo "$int is negative."
    else
    echo "$int is positive."
    fi

    if (( ((int % 2)) == 0)); then
    echo "$int is even."
    else
    echo "$int is odd."
    fi
    fi
  • Reading a password:

    read-pass.sh
    #!/bin/bash

    # -e: use readline to get the input
    # -p: display a prompt
    # -i: provide a default reply
    read -e -p "What is your user name > " -i $USER username
    echo "Welcome '$username'"

    # -t: timeout (in seconds)
    # -s: silent (do not echo characters to the display as they are typed)
    # -p: display a prompt
    if read -t 10 -sp "Enter your secret passphrase > " secret_pass
    then
    echo -e "\nYour secret passphrase is '$secret_pass'"
    else
    echo -e "\nInput timed out" >&2
    exit 1
    fi

5. Parameters

  • params.sh:

    #!/bin/bash
    # view command line parameters

    echo "
    \$0 = $0
    \$1 = $1
    \$2 = $2
    \$3 = $3
    \$4 = $4
    \$5 = $5
    \$6 = $6
    \$7 = $7
    \$8 = $8
    \$9 = $9
    Number of arguments: $#
    "
    ./params.sh a b c d
  • Calculate the Fibonacci numbers:

    fibo.sh
    #!/bin/bash

    N=$1
    if [[ -z $N ]]; then
    echo "Usage: $0 <n>" >&2
    exit 1
    fi

    [[ $N == 0 ]] && echo 0 && exit
    [[ $N == 1 ]] && echo 1 && exit

    f0=0
    f1=1
    for ((i=1; i<N; i++)); do
    fib=$((f0 + f1))
    f0=$f1
    f1=$fib
    done
    echo $f1
    ./fibo.sh
    for i in {0..10}; do ./fibo.sh $i; done
    ./fibo.sh 100

6. Functions

  • Testing integers, with a function and a loop:

    test-int-2.sh
    #!/bin/bash

    check() {
    local int=$1

    if [[ ! $int =~ ^-?[0-9]+$ ]]; then
    echo "Input value is not an integer." >&2
    return 1
    fi

    if ((int == 0)); then
    echo "$int is zero."
    else
    if ((int < 0)); then
    echo "$int is negative."
    else
    echo "$int is positive."
    fi

    if (( ((int % 2)) == 0)); then
    echo "$int is even."
    else
    echo "$int is odd."
    fi
    fi
    }

    while true; do
    echo
    read -p "Please enter an integer -> " int
    check $int
    done

    At the top of the function check() add this line, and try again:

    [[ $int == 'q' ]] && exit

    This makes it possible to stop the script by pressing q (instead of terminating it with Ctrl+c).

  • Testing files and their properties:

    test-file.sh
    #!/bin/bash

    usage() {
    cat <<EOF
    Usage: $0 <path>

    where <path> is a file or a directory.

    EOF
    exit 1
    }

    # evaluate the status of a file
    test_file() {
    local file=$1

    if [[ ! -e $file ]]; then
    echo "$file does not exist"
    return 1
    else
    # test using the command 'test'
    if test -f $file ; then
    echo "$file is a regular file."
    fi

    # test using [...]
    if [ -d $file ]; then
    echo "$file is a directory."
    fi

    # test using [[...]]
    if [[ -r $file ]]; then
    echo "$file is readable."
    fi

    [[ -w $file ]] && echo "$file is writable."

    [[ ! -x $file ]] \
    || echo "$file is executable/searchable."
    fi
    }

    # [[ -z $1 ]] && usage
    [[ -n $1 ]] || usage

    # call the function
    test_file $1
    ./test-file.sh
    ./test-file.sh ~/.bashrc
    ./test-file.sh ~/.ssh
    ./test-file.sh ~/root
    ./test-file.sh test-integer-1.sh
    ./test-file.sh .
    ./test-file.sh test-file.sh
    ./test-file.sh foo.txt
    touch foo.txt
    ./test-file.sh foo.txt
    rm foo.txt

7. Case

  • Case with patters:

    case.sh
    #!/bin/bash

    case "$1" in
    [[:alpha:]])
    echo "it is a single alphabetic character"
    ;;
    [ABC][0-9])
    echo "it is A, B, or C followed by a digit"
    ;;
    ???)
    echo "it is three characters long"
    ;;
    *.txt)
    echo "it is a word ending in '.txt'"
    ;;
    *)
    echo "it is something else"
    ;;
    esac
    ./case.sh x
    ./case.sh B2
    ./case.sh foo.txt
    ./case.sh xyz
    ./case.sh ab
    ./case.sh x
  • A menu driven system information program:

    menu.sh
    #!/bin/bash
    # a menu driven system information program

    main() {
    while true; do
    display_menu
    read -p "Enter selection [A, B, C or Q] > "
    echo
    process_selection $REPLY
    echo
    read -p "Press <enter> to continue..."
    done
    }

    display_menu() {
    clear
    cat <<_EOF_

    A. Display System Information
    B. Display Disk Space Utilization
    C. Display Home Space Utilization
    Q. Quit

    _EOF_
    }

    process_selection() {
    local selection=$1
    case $selection in
    q|Q) echo -e "Program terminated. \n"
    exit
    ;;
    a|A) echo -e "A. System Information \n"
    echo Hostname: $HOSTNAME
    uptime
    ;;
    b|B) echo -e "B. Disk Space Utilization \n"
    df -h .
    ;;
    c|C) echo -e "C. Home Space Utilization \n"
    display_home_space_utilization
    ;;
    *) echo "Invalid entry: '$selection'"
    ;;
    esac
    }

    display_home_space_utilization() {
    if [[ "$(id -u)" -eq 0 ]]; then
    echo "Home Space Utilization (All Users)"
    du -sh /home/*
    else
    echo "Home Space Utilization ($USER)"
    du -sh $HOME
    fi
    }

    # call main
    main "$@"