You may remember being able to watch a 17 minute ASCII animation of Star Wars IV in terminal, from ~15 years ago (I remember watching it on my primary school’s library computers).

(You can download my MOTD bash script here)

Well over a decade later we can still watch it using telnet. By typing into our terminal:

$ telnet towel.blinkenlights.nl

We would like to write a bash script which on the first execution saves each frame of the animation to a file, and upon subsequent excecutions, print a random frame to the terminal.

First we need to download each frame of the ASCII Star Wars animation. Each frame is separated by the character sequence ^[[H .

We pipe the output of telnet into a command sed which allows us to perform a regular expression command on the frames. We use regex ‘s/.[H/Z/g’ to replace every occurence of ^[[H with Z .

$ telnet towel.blinkenlights.nl | sed -e 's/.\[H/Z/g'

( Z conveniently does not appear elsewhere in the animation) Next we want to use tee to output this to a file mainScenes :

$ telnet towel.blinkenlights.nl | sed -e 's/.\[H/Z/g' | tee mainScenes

We sit through the whole animation as it saves each frame to the file.

$ cat mainScenes . . / / \ \ === , | |>< > | | Come on! @o o@ ) | ( / \_ _ ) | \- / | / \ | / \ | || / (=== o | / ( ) \ | | / \ | | /_/ \ / \_ | | \/ ][][ \/ | || \ // || | | \ /| | @ | | | @ | |_||_| | | | | | [ ][ ] | | | | | | || | | / | \ | | || | | ~~~~~~~ ______|___/__][_]___|___________________________/__ )( _ ) ____________Z / / \ \ === , | |>< > | | @o o@ ) | ( / \_ _ ) | \- / | / \ | /~~ ~~ \ | || / (=== o | / ( ) \ | | / \ | | /_/ \ / \_ | | \/ ][][ \/ | || \ // || | | \ /| | @ | | | @ | |_||_| | | | | | [ ][ ] | | | | | | || | | / | \ | | || | | ~~~~~~~ ______|___/__][_]___|___________________________/__ )( _ ) ____________Z

We can see each frame is now separated by character Z .

Now we wish to load this file mainScenes and save each frame to an individual file. We open the file into a variable $SCENEDATA :

SCENEDATA = $( < "mainScenes" )

And then we split this string, on each occurence of Z , into an array $SCENES using an Internal Field Separator (IFS):

IFS = $'Z' read -d '' -ra SCENES <<< " $SCENEDATA "

Next we loop over an index for each scene, through numbers 115- with seq 115 ${#SCENES[@]} . We start from scene #115 to skip the classic Star Wars scrolling text intro. During the loop we echo each scene into a file starshell/s_INDEX . You should mkdir starshell yourself:

$SCENEDIR = starshell # Save "good" scenes to files for SCENENUM in $( seq 115 ${# SCENES [@] } ) ; do echo " ${ SCENES [ $SCENENUM ] } " >> $SCENEDIR /s_ $SCENENUM done

We can see all the scenes:

$ ls -l starshell/

-rw-r--r-- 1 nick nick 968 Jun 6 04:54 s_1000 -rw-r--r-- 1 nick nick 968 Jun 6 04:54 s_1001 -rw-r--r-- 1 nick nick 968 Jun 6 04:54 s_1002 ...

Now all that is left is to randomly choose a scene to print to the terminal. We choose randomly by listing the $SCENEDIR directory, and then pipe each filename into shuf ; which randomly sorts them, then chooses the first one with flag -n 1 :

$ echo " $( < $( ls " $SCENEDIR /s_" * | shuf -n 1 )) "

Upon running this a random scene is displayed!

/~ \ | _______ ( oo| | "" / \ ooo * _ \= /_ | :. |__[]_[]__| o * o * / \ ___ | |__ _ __| * oo * //|/. \|\\ / () \ | ## | [] [] | o*oo || \_ / || _|_____|_ | ## \_______/ || | \ /| || | | === | | |______________________ # \_ _/ # |_| O |_| / | | | || O || |------------------------ | | | || __ * __|| | ( * ) [] |[] |~ \_ __/ ~| | | | | / = \ / = \ / = \ | ____/_]_[_ \_ __________________[_]_[_]_[_]_|________________________

Let’s wrap this all up into a single file:

#!/bin/bash # Nicholas Farrow 2019 CFGLOC = ~/.config SCENEDIR = $CFGLOC /starshell STARTSCENE = 115 # Make folder if doesn't exist [ -d $SCENEDIR ] || mkdir $SCENEDIR # If $STARTSCENE scene file does not exist, save starwars to file if [ ! -f $SCENEDIR /s_ $STARTSCENE ] ; then telnet towel.blinkenlights.nl | sed -e 's/.\[H/Z/g' | tee $SCENEDIR /main SCENEDATA = $( < " $SCENEDIR /main" ) # Load scenes IFS = $'Z' read -d '' -ra SCENES <<< " $SCENEDATA " echo ${# SCENES [@] } # Save "good" scenes to invividual files for SCENENUM in $( seq 115 ${# SCENES [@] } ) ; do echo " ${ SCENES [ $SCENENUM ] } " >> $SCENEDIR /s_ $SCENENUM echo $SCENENUM done fi # Print random scene echo " $( < $( ls " $SCENEDIR /s_" * | shuf -n 1 )) "

Save this script in your home directory like ~/.config/starshell.sh , and make it excecutable with chmod +x ~/.config/starshell.sh . If you want a scene automatically displayed each time you open a terminal then in your ~/.bashrc or ~/.bash_profile we add the line:

source ~/.config/starshell.sh

Now every time we open a new terminal a nice scene is displayed! (majority of scenes are quite nice).

I would love for someone to try this on Mac OSX, let me know if it works out!

Or alternatively we can manually print out a new scene by typing: