Fireworks from the Command Line

 in

To kick off the upcoming 4th of July celebrations we present the following bash script for your enjoyment.

If you'd rather not try to figure out what it does, watch the video.

Have a safe and Happy 4th of July!

#!/bin/bash

rows=$(tput lines)
cols=$(tput cols)
colors=(red green blue purple cyan yellow brown)
lock_file=
lock_file_base=/tmp/$(basename $0 .sh)

multiple=0
if [[ "$1" ]]; then
    nsingle=$1
    shift
else
    nsingle=10
fi
if [[ "$1" ]]; then
    nmultiple=$1
    shift
    if [[ $nmultiple -gt 8 ]]; then nmultiple=8; fi
else
    nmultiple=6
fi


function colorstr()
{
    local  row=$1
    local  col=$2
    local  color=$3
    local  v
    case "$color" in
    red)     v=31;;
    green)   v=34;;
    blue)    v=32;;
    purple)  v=35;;
    cyan)    v=36;;
    yellow)  v=33;;
    brown)   v=33;;
    white)   v=37;;
    *)       v=;;
    esac
    shift 3

    if [[ $multiple -ne 0 ]]; then
        touch $lock_file
        while [[ $(ls $lock_file_base.* 2>/dev/null | head -n 1) != $lock_file ]]
        do
            sleep 0.05
        done
    fi
        
    tput cup $row $col
    echo -n -e "\e["$v"m"
    set -f
    echo -n $*
    set +f
    if [[ $multiple -ne 0 ]]; then
        rm -f $lock_file
    fi
}

function center_colorstr()
{
    local  row=$1
    local  color=$2
    shift 2
    local  s="$*"
    local  slen=${#s}
    colorstr $row $(((cols / 2) - (slen / 2))) $color "$s"
}

function fireworks()
{
    local row=$((rows - 1))
    local col=$(((RANDOM % (cols / 2)) + (cols / 4)))
    local height=$((RANDOM % rows - 2))
    local slant
    local h
    local color1=${colors[$((RANDOM % ${#colors[*]}))]}
    local color2=${colors[$((RANDOM % ${#colors[*]}))]}
    local color3=${colors[$((RANDOM % ${#colors[*]}))]}
    while [[ $color1 == $color2  ||  $color1 == $color3  ||  $color2 == $color3 ]]
    do
        color2=${colors[$((RANDOM % ${#colors[*]}))]}
        color3=${colors[$((RANDOM % ${#colors[*]}))]}
    done

    case $((RANDOM % 4)) in
    0) slant=-2;;
    1) slant=-1;;
    2) slant=1;;
    3) slant=2;;
    esac

    if [[ $height -gt 5 ]]; then
        h=$height

        while [[ $h -gt 0 ]]
        do
            colorstr $row $col $color1 '.'
            let row--
            if [[ $((col + slant)) -ge $((cols - 3))  ||  $((col + slant)) -le 2 ]]; then break; fi
            let col+=slant
            let h--
            sleep 0.1
        done

        if [[ $((col + slant)) -lt $((cols - 3))  &&  $((col + slant)) -gt 2 ]]; then

            h=$((height / 5))

            while [[ $h -gt 0 ]]
            do
                colorstr $row $col $color2 '.'
                let row++
                if [[ $((col + slant)) -ge $((cols - 3))  ||  $((col + slant)) -le 2 ]]; then break; fi
                let col+=slant
                let h--
                sleep 0.1
            done
        fi

        colorstr $((row)) $((col - 1)) $color3 '***'
        colorstr $((row - 1)) $((col)) $color3 '*'
        colorstr $((row + 1)) $((col)) $color3 '*'
    fi
}

for i in $(seq 1 $nsingle)
do
    clear
    fireworks
    sleep 1
done

clear

pids=
for i in $(seq 1 $nmultiple)
do
    let multiple++
    lock_file=$lock_file_base.$i
    fireworks &
    pids="$pids $!"
done

trap "kill -9 $pids 2>/dev/null" EXIT

wait $pids
sleep 3

clear
center_colorstr $((rows / 2 - 1)) red "Hope you enjoyed the show!"
center_colorstr $((rows / 2 + 1)) red "Happy 4th of July"
center_colorstr $((rows / 2 + 3)) red "Your Friends at Linux Journal"
echo

sleep 5
clear


# vim: tabstop=4: shiftwidth=4: noexpandtab:
# kate: tab-width 4; indent-width 4; replace-tabs false;
AttachmentSize
happy4j.sh_.txt2.89 KB
______________________

Mitch Frazier is an Associate Editor for Linux Journal.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Thanks

JimmyK's picture

Thanks! A tip o' the hat to ye </:-0 . This inspired me to get back to learning bashscripts at bashscripts.org. I've been neglecting my mind and forgot how to even run a script :-( JimmyK

Syntax error?

Technoslick's picture

Copied/pasted script text to new file as well as tired saving/renaming article link for script text to new file. When run:

happy4j.sh: 5: Syntax error: "(" unexpected

???

Ubuntu 9.04 Jaunty

Not Bash

Mitch Frazier's picture

At some point Ubuntu stopped making bash the default shell and changed to dash, so if you run the script via "sh happy4j.sh" you end up running it with dash rather than bash. Run it via "bash happy4j.sh" or make it executable with "chmod +x happy4j.sh" and then run it directly via "./happy4j.sh".

I'm not an Ubuntu user so I tend to assume that sh == bash... I probably should stop doing that.

So you may be wondering "what's the value of the shebang (#!) at the top of a script if it doesn't work with all shells?" Well, the answer is that the shebang is not understood by shells: it's understood by the O/S itself. That's why making the script executable and running it directly works.

When the O/S (Linux) opens an executable file (something that has the x bit set) it reads the first two bytes and checks to see if they are equal to "#!". If they are equal, the O/S then executes the program specified in the remainder of the first line rather than the original file and passes the original file name to it as an argument.

Mitch Frazier is an Associate Editor for Linux Journal.

Thanks! Left my bash prompt

Jon Brett's picture

Thanks!

Left my bash prompt a red colour after the show - or maybe that's just my eyes having been dazzled ;)

Reset Color on Exit

Mitch Frazier's picture

Add the following line to the end of the script.

echo -n -e "\e[m"

That should reset the color.

Mitch Frazier is an Associate Editor for Linux Journal.

Retro ASCII Goodness

Tony Miller's picture

Ahhh, this brings back memories of getting the latest computer mag in the 80s, typing in the listing, and hoping for the best. Now, though, I can copy and paste from a web browser into vim, save, chmod, and sit back and enjoy the show.

Very nice old skool display. Thanks!

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix