--- /dev/null
+#!/bin/bash
+# Desc: Sums newline-delimited floats received from stdin
+# Usage: some_app | sumFloat
+# Example: printf -- "-3\n0.14" | sumFloat
+# Result: -2.860000
+# Version: 0.0.2
+# Depends: bc 1.07.1
+
+yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
+dief() { yell "$*"; return 111; } # same as yell() but non-zero return status
+must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
+sum_float() {
+ # Desc: Sums newline-delimited floats received on stdin
+ # Usage: some_app | sum_float
+ # Depends: bc 1.07.1, paste (GNU coreutils)
+
+ # Check dependencies
+ command -v bc 1>/dev/random 2>&1 || { dief "FATAL:Missing:bc"; };
+ [[ ! -t 0 ]] || { dief "FATAL:No stdin detected."; };
+
+ # Process lines
+ local line re; local -a nums=();
+ re='^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$';
+ while IFS= read -r line; do
+ [[ -z $line ]] && continue;
+ [[ $line =~ $re ]] || { dief "FATAL:Not a float:${line}"; };
+ nums+=("$line");
+ done;
+
+ # Print output
+ if (( ${#nums[@]} == 0 )); then printf '0.000000\n'; return 0; fi;
+ LC_ALL=C printf '%.6f\n' "$(printf '%s\n' "${nums[@]}" | paste -sd+ - | bc -l)";
+} # sum stdin floats
+
+# Author: Steven Baltakatei Sandoval
+# License: GPLv3+
# Note: All three functions should be added together if used at all.
# Ref/Attrib: [1] Yell, Die, Try Three-Fingered Claw technique https://stackoverflow.com/a/25515370
# Depends: GNU Coreutils 8.30
-# Version 1.0.0
+# Version 1.0.1
#==BEGIN Define script parameters==
#==END Define script parameters==
#===BEGIN Declare local script functions===
yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+dief() { yell "$*"; return 111; } # same as die() but meant for functions to avoid exiting main shell
must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
#===END Declare local script functions===
# Desc: Searches for erotic phrases in text files in specified working directory
# Usage: find_erotica.sh [dir]
# Depends: GNU Find utils, GNU Parallel 20210822, GNU Grep, GNU Coreutils 8.32, bc
-# Version: 0.3.0
+# Version: 0.4.0
FIN_MAX=400;
#printf "Found %d matching lines for phrases in %s.\n" "${#output[@]}" "$fin" 1>&2; # debug
}; # find phrase
main () {
- din="$1";
- if [[ ! -d "$din" ]]; then die "FATAL:Not a dir:${din}"; fi;
+ # Check args are dirs
+ local item;
+ for item in "$@"; do
+ if [[ ! -d "$item" ]]; then die "FATAL:Not a dir:${din}"; fi;
+ done;
- find "$din" -type f -name "*.txt" | shuf | head -n "$FIN_MAX" | \
+ find "$@" -type f -name "*.txt" | shuf | head -n "$FIN_MAX" | \
#parallel search_thread '{}' | less --RAW-CONTROL-CHARS -S;
parallel search_thread '{}';
};
--- /dev/null
+#!/bin/bash
+# Desc: Analyzes photo files selected in gThumb; shows size/time/GPS
+# statistics in a zenity dialog. Intended for evaluating burst-mode
+# sequences where larger JPEG size correlates with sharpness.
+# Usage: gthumb-analyze.sh FILE…
+# Example: $HOME/.local/bin/gthumb-analyze.sh %F
+# Depends: bash, GNU coreutils, awk, bc, column (util-linux 2.39.3)
+# exiftool (12.x), GNU sed 4.9, zenity
+# Version: 0.0.9
+
+fdebug=/tmp/gtAnalyzeLog.txt;
+
+yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
+die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
+main() {
+ # Validate inputs
+ local fina fin cmd;
+ fina=("$@");
+ if [[ $# -le 0 ]]; then die "FATAL:No arguments:$#"; fi;
+ for fin in "${fina[@]}"; do
+ if [[ ! -f "$fin" ]]; then die "FATAL:Not a file:${fin}"; fi;
+ done;
+ for cmd in awk bc column cut exiftool sed sort zenity; do
+ command -v "$cmd" >/dev/null 2>&1 || die "FATAL:Missing dependency:${cmd}";
+ done;
+
+ # Single batched exiftool pass. Columns (tab-separated):
+ # col 1: FileName
+ # col 2: FileSize [bytes]
+ # col 3: SubSecCreateDate [float POSIX seconds]
+ # col 4: GPSPosition [±Lat, ±Lon]
+ # col 5: FNumber [float]
+ # col 6: ExposureTime [str seconds]
+ # col 7: ISO [int]
+ # col 8: FocalLength [str %.01f mm]
+ # Note: Missing tags emit '-' in -T mode.
+ local tsv;
+ tsv="$(exiftool -q -T -FileName '-FileSize#' \
+ -SubSecCreateDate -d '%s%f' \
+ -GPSPosition -c '%+0.4f' \
+ -FNumber -ExposureTime -ISO -FocalLength \
+ -- "${fina[@]}")" \
+ || die "FATAL:exiftool failed";
+ yell "DEBUG:tsv:"; printf '%s\n' "$tsv" 1>&2;
+
+ local n fMax fMaxArr fMin fMinArr mean sdev median span gps;
+ n="$(printf '%s\n' "$tsv" | wc -l)";
+
+ # First and last by file name
+ local fFirst fLast;
+ fFirst="$(printf '%s\n' "$tsv" | sort -t$'\t' -k1,1 | head -n1 | cut -f1)";
+ fLast="$(printf '%s\n' "$tsv" | sort -t$'\t' -k1,1 | tail -n1 | cut -f1)";
+
+ # Largest and smallest files by size (numeric sort on column 2)
+ fMax="$(printf '%s\n' "$tsv" | sort -t$'\t' -k2,2n | tail -n1)";
+ fMin="$(printf '%s\n' "$tsv" | sort -t$'\t' -k2,2n | head -n1)";
+ fMaxArr[0]="$(cut -f1 <<< "$fMax")";
+ fMaxArr[1]="$(cut -f2 <<< "$fMax")";
+ fMinArr[0]="$(cut -f1 <<< "$fMin")";
+ fMinArr[1]="$(cut -f2 <<< "$fMin")";
+ ## Avoid & or < being parsed as markup by zenity
+ fMaxArr[0]="$(sed -e 's/&/\&/g' -e 's/</\</g' <<< "${fMaxArr[0]}")";
+ fMinArr[0]="$(sed -e 's/&/\&/g' -e 's/</\</g' <<< "${fMinArr[0]}")";
+
+ # Mean and population standard deviation (÷N, not N−1: the
+ # selection is the entire population of interest).
+ read -r mean sdev < <(printf '%s\n' "$tsv" | cut -f2 \
+ | awk '{s+=$1; ss+=$1*$1;} END {m=s/NR; printf "%.0f %.0f\n", m, sqrt(ss/NR - m*m);}');
+
+ # Median file size
+ median="$(printf '%s\n' "$tsv" | cut -f2 | sort -n \
+ | awk '{a[i++]=$1;} END {if (i%2==0) {printf "%.0f\n", (a[i/2-1]+a[i/2])/2;} else {print a[int(i/2)];};}')";
+
+ # Time span in seconds via bc; ignore files lacking dates.
+ local tMin tMax;
+ tMin="$(printf '%s\n' "$tsv" | cut -f3 | grep -v '^-$' | sort -n | head -n1)";
+ tMax="$(printf '%s\n' "$tsv" | cut -f3 | grep -v '^-$' | sort -n | tail -n1)";
+ if [[ -n "$tMin" && -n "$tMax" ]]; then
+ span="$(printf "%'.3f s" "$(bc -l <<< "${tMax} - ${tMin}")")"; # seconds
+ else
+ span="n/a (missing SubSecCreateDate)";
+ fi;
+
+ # GPS: single unique value, none, or multiple.
+ local gpsUniq gpsUniqSamp gpsCount;
+ gpsUniq="$(printf '%s\n' "$tsv" | cut -f4 | sort -u | grep -v '^-$')";
+ gpsCount="$(printf '%s\n' "$gpsUniq" | grep -c .)";
+ case "$gpsCount" in
+ 0) gps="none";;
+ *) gps="(${gpsCount} distinct)";
+ mapfile -t gpsUniqSamp < <(shuf <<< "$gpsUniq" | head -n8 | sort);;
+ esac;
+
+ # Exposure combos: unique (FNumber, ExposureTime, ISO, FocalLength) tuples.
+ # Missing tags appear as '-' and still compare consistently.
+ local expUniq expUniqSamp expCount exp;
+ expUniq="$(printf '%s\n' "$tsv" | cut -f5-8 | sort -u \
+ | awk -F'\t' '{printf "f/%s\t%s s\tISO %s\t%s\n", $1, $2, $3, $4;}')";
+ mapfile -t expUniqSamp < <(shuf <<< "$expUniq" | head -n8 | sort -t $'\t' -k4,4n);
+
+ expCount="$(printf '%s\n' "$expUniq" | grep -c .)";
+ case "$expCount" in
+ 1) exp="uniform";;
+ *) exp="${expCount} distinct combinations";;
+ esac;
+
+ # Report
+ local msgSec1Arr msgSec1 msgSec2Arr msgSec2 msgSec3Arr msgSec3 msg;
+ ## Assemble message section 1 (file size, time span)
+ msgSec1Arr+=("$(printf "%d files analyzed (About %d s)" "$n" "$SECONDS")");
+ msgSec1Arr+=("$(printf "First:\t\t%s" "$fFirst")");
+ msgSec1Arr+=("$(printf "Last:\t\t%s" "$fLast")");
+ msgSec1Arr+=("$(printf "%s" "----" )");
+ msgSec1Arr+=("$(printf "Largest:\t%'d B\t%s" "${fMaxArr[1]}" "${fMaxArr[0]}")");
+ msgSec1Arr+=("$(printf "Smallest:\t%'d B\t%s" "${fMinArr[1]}" "${fMinArr[0]}")");
+ msgSec1Arr+=("$(printf "Mean size:\t%'d B" "$mean")");
+ msgSec1Arr+=("$(printf "Median size:\t%'d B" "$median")");
+ msgSec1Arr+=("$(printf "Std. dev.:\t%'d B" "$sdev")");
+ msgSec1Arr+=("$(printf "Time span:\t%s" "$span")");
+ msgSec1="$(printf '%s\n' "${msgSec1Arr[@]}" | column -s $'\t' -t --table-right 2)";
+ ## Assemble message section 2 (location)
+ msgSec2Arr+=("$(printf "GPS:\t%s" "$gps")");
+ msgSec2Arr+=("$(printf '%s\n' "${gpsUniqSamp[@]}")");
+ msgSec2="$(printf '%s\n' "${msgSec2Arr[0]}"; printf '%s\n' "${msgSec2Arr[@]:1}" | column -s $'\t' -t | sed -e 's/^/\t/')";
+ ## Assemble message section 3 (exposure)
+ msgSec3Arr+=("$(printf "Exposure:\t%s" "$exp")");
+ msgSec3Arr+=("$(printf '%s\n' "${expUniqSamp[@]}")");
+ msgSec3="$(printf '%s\n' "${msgSec3Arr[0]}"; printf '%s\n' "${msgSec3Arr[@]:1}" | column -s $'\t' -t | sed -e 's/^/\t/')";
+ ## Assemble combined message
+ msg="$(printf '%s\n--------\n' "$msgSec1" "$msgSec2" "$msgSec3")";
+ ## Display message
+ zenity --info --title="gThumb-analyze.sh stats" --no-wrap --text="<span font='monospace'>${msg}</span>";
+};
+
+main "$@" 1>>"$fdebug" 2>&1;
+
+# Author: Steven Baltakatei Sandoval
+# License: GPLv3+
+
--- /dev/null
+#+AUTHOR: Steven Baltakatei Sandoval
+#+DATE: 2026-08-02
+#+TITLE: gThumb prune
+
+** Summary
+This work describes a way to quickly move groups of photograph files
+(e.g. ~DSC00001.JPG~, ~DSC00001.ARW~, etc.) as well as associated
+sidecar files into desired directories via keyboard shortcuts in
+gThumb.
+
+The method centers around a Bash script named ~gthumb-prune.sh~ which
+may be bound to a gThumb keyboard shortcut to quickly move selected
+image files to a desired location. The Bash script is run by a short
+shell script specified in gThumbʼs 🔧 → Personalize… menu.
+Additionally, sidecar files as well as associated files sharing the
+same file name stem (i.e. ~../*/DSC00001.*~) are also grouped and
+moved to the desired location.
+
+** Stats
+Version: 0.0.4
+License: GPLv3+
+gThumb version: ~3.12.6~
+
+** Usage
+Let us say, that we have a set of photos in the following
+locations:
+
+#+begin_example
+.
+├── ARW
+│ ├── DSC00001.ARW
+│ ├── DSC00001.ARW.ots
+│ ├── DSC00002.ARW
+│ ├── DSC00002.ARW.ots
+│ ├── DSC00003.ARW
+│ └── DSC00003.ARW.ots
+└── JPG
+ ├── DSC00001.JPG
+ ├── DSC00001.JPG.ots
+ ├── DSC00002.JPG
+ ├── DSC00002.JPG.ots
+ ├── DSC00003.JPG
+ └── DSC00003.JPG.ots
+#+end_example
+
+Let us say gThumb has the ~JPG~ directory open and we have selected
+~DSC00002.JPG~ which we want to keep. We also want to keep the
+associated ~DSC00002.JPG.ots~ as well as the ~DSC00002.ARW~ and
+~DSC00002.ARW.ots~ files in the neighboring ~ARW~ directory. We wish
+to discard all other photograph files.
+
+First, we configure a ~keep~ shortcut. In the gThumbʼs 🔧 →
+Personalize… menu, click the *New* button. Set the *Name* to
+~keep~. Set the *Command* to:
+
+: fscript="$HOME/.local/bin/gthumb-prune.sh"; if [ -f "$fscript" ]; then /bin/bash "$fscript" "keep" %F; fi;
+
+Where ~$HOME/.local/bin/gthumb-prune.sh~ is the path for the Bash
+script (see the ~Code~ section below).
+
+Set the *Shortcut* to ~Shift+K~. Make sure the box “Terminal command
+(shell script)” box is checked and the “Execute command once for every
+file” is *not* checked. Click the *Save* button to close the ~Edit
+Command~ window. Click the *Ok* button to close the ~Commands~ window.
+
+Now, with ~DSC00002.JPG~ selected, press ~Shift+K~ on your
+keyboard. The image should disappear from view and a new directory
+should appear in the left navbar, reflecting a new directory structure.
+
+#+begin_example
+.
+├── ARW
+│ ├── DSC00001.ARW
+│ ├── DSC00001.ARW.ots
+│ ├── DSC00003.ARW
+│ └── DSC00003.ARW.ots
+├── JPG
+│ ├── DSC00001.JPG
+│ ├── DSC00001.JPG.ots
+│ ├── DSC00003.JPG
+│ └── DSC00003.JPG.ots
+└── keep
+ ├── ARW
+ │ ├── DSC00002.ARW
+ │ └── DSC00002.ARW.ots
+ └── JPG
+ ├── DSC00002.JPG
+ └── DSC00002.JPG.ots
+#+end_example
+
+The ~DSC00002.*~ files (4 in total) have been moved to now reside
+within a ~keep~ directory with their ~JPG~ and ~ARW~ subdirectory
+structure preserved. Thus, the ~./JPG/~ and ~./ARW/~ directories have
+been pruned.
+
+If we want to trash the remaining ~DSC00001.*~ and ~DSC00003.*~ files,
+we can create another shortcut to group and move files into a ~.trash~
+directory next to ~keep~.
+
+Repeat the procedure for creating a shortcut, but *Name* it ~rmall~
+and set the *Command* to be:
+
+: fscript="$HOME/.local/bin/gthumb-prune.sh"; if [ -f "$fscript" ]; then /bin/bash "$fscript" ".trash" %F; fi;
+
+Note the change from ~keep~ to ~.trash~. Set the keyboard *Shortcut*
+to ~Shift+T~.
+
+Now, with gThumb looking at the contents of ~./JPG~, and with
+~DSC00001.JPG~ and ~DSC00003.JPG~ selected, press ~Shift+T~. The two
+images should disappear, leaving ~./JPG~ now empty. The navbar to the
+left should not show any change since ~.trash~ is a dot directory and
+so is normally hidden. Nonetheless, the directory structure has now
+changed to:
+
+#+begin_example
+.
+├── ARW
+├── JPG
+├── keep
+│ ├── ARW
+│ │ ├── DSC00002.ARW
+│ │ └── DSC00002.ARW.ots
+│ └── JPG
+│ ├── DSC00002.JPG
+│ └── DSC00002.JPG.ots
+└── .trash
+ ├── ARW
+ │ ├── DSC00001.ARW
+ │ ├── DSC00001.ARW.ots
+ │ ├── DSC00003.ARW
+ │ └── DSC00003.ARW.ots
+ └── JPG
+ ├── DSC00001.JPG
+ ├── DSC00001.JPG.ots
+ ├── DSC00003.JPG
+ └── DSC00003.JPG.ots
+#+end_example
+
+So, the contents of ~./JPG/~ may be pruned by selecting files you want
+to keep and pressing ~Shift+K~ and by selecting files you want to
+trash and pressing ~Shift+T~. Then, if you are really sure about
+deleting the undesired files, delete the contents of ~.trash~ via the
+terminal command:
+
+: $ rm -r ./.trash
+
+** Code
+gthumb-prune.sh:
+
+#+begin_src bash
+#!/bin/bash
+# Desc: Prunes files selected by gThumb.
+# Note: Moves files into a directory with a specified name.
+# Usage: gthumb-prune.sh DIRNAME FILES…
+# Example: $HOME/.local/bin/gthumb-prune.sh keep %F
+# If '%F' expanded to `~/Pics/MyJPGs/DSC00001.JPG`, then
+# "$HOME/Pics/*/DSC00001.*" files are moved to:
+# '~/Pics/keep/MyJPGs/' .
+#
+# If '%F' expanded to multiple files, then the move
+# operations to 'keep' are performed for each file.
+# Input: arg1 str directory to send selected files
+# arg2+ str path of selected file(s)
+# Version: 0.0.4
+
+fdebug=/tmp/gtPruneLog.txt;
+
+yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
+die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
+main() {
+ # Validate inputs
+ local groupName re1 fina;
+ ## Interpret first argument as name of group directory to move files into.
+ groupName="$1"; # e.g. 'keep'
+ ### RegEx matches:
+ ### - Forward slash (i.e. path) anywhere.
+ ### - A string consisting of just '.' (current working dir)
+ ### - A string consisting of just '..' (parent dir of working dir)
+ re1='/|^\.$|^\.\.$';
+ if [[ "$groupName" =~ $re1 ]]; then
+ die "FATAL:Group '${groupName}' must not be a path.";
+ fi;
+ if [[ -z "$groupName" ]]; then
+ die "FATAL:Group '${groupName}' may not be blank.";
+ fi;
+ shift;
+
+ ## Interpret remaining arguments as files and populate input file array
+ fina=("$@");
+
+ ## Validate input file array
+ ### Handle no argument case.
+ if [[ $# -le 0 ]]; then
+ die "FATAL:No arguments:$#";
+ fi;
+ ### Check each remaining array element is a file.
+ local fin;
+ for fin in "${fina[@]}"; do
+ if [[ ! -f "$fin" ]]; then
+ die "FATAL:Not a file:${fin}";
+ fi;
+ done;
+
+
+ # Process each file
+ local f;
+ for f in "${fina[@]}"; do
+ # Set up variables
+ local fBase dParent dParParent fNoExt dGroup;
+ fBase="$(basename "$f")";
+ dParent="$(dirname "$f")";
+ dParParent="$(dirname "$dParent")";
+ fNoExt="${fBase%.*}";
+ dGroup="${dParParent}/${groupName}";
+ yell "DEBUG:fdebug:${fdebug}";
+ yell "DEBUG:f:${f}"; # e.g. ~/Pics/MyJPGs/DSC00001.JPG
+ yell "DEBUG:fBase:${fBase}"; # e.g. DSC00001.JPG
+ yell "DEBUG:fNoExt:${fNoExt}"; # e.g. DSC00001
+ yell "DEBUG:dParent:${dParent}"; # e.g. ~/Pics/MyJPGs/
+ yell "DEBUG:dParParent:${dParParent}"; # e.g. ~/Pics/
+ yell "DEBUG:dGroup:${dGroup}"; # e.g. ~/Pics/keep/
+
+ # Move sibling files sharing the stem
+ local fSrc subDirName dDest;
+ for fSrc in "${dParParent}"/*/"${fNoExt}".*; do
+ if [ ! -e "$fSrc" ]; then continue; fi;
+ subDirName="$(basename "$(dirname "$fSrc")")";
+ dDest="${dGroup}/${subDirName}";
+ yell "DEBUG:fSrc:${fSrc}"; # e.g. ~/Pics/MyARWs/DSC00001.ARW.ots
+ yell "DEBUG:subDirName:${subDirName}"; # e.g. MyARWs
+ yell "DEBUG:dDest:${dDest}"; # e.g. ~/Pics/keep/MyARWs/
+ if [ ! -d "$dDest" ]; then
+ yell "STATUS:Destination dir does not exist. Creating:${dDest}";
+ must mkdir -p "$dDest";
+ else
+ yell "STATUS:Destination dir exists:${dDest}";
+ fi;
+ yell "STATUS: Moving ${fSrc} → ${dDest}/";
+
+ # Perform move ( e.g. mv ~/Pics/MyARWs/DSC00001.ARW.ots ~/Pics/keep/MyARWs/ )
+ mv -n "$fSrc" "${dDest}/";
+
+ # Check if move failed.
+ if [[ -e "$fSrc" ]]; then
+ yell "ERROR:Failed to move ${fSrc} → ${dDest}";
+ fi;
+ done;
+ done;
+};
+
+main "$@" 1>>"$fdebug" 2>&1;
+
+# Author: Steven Baltakatei Sandoval
+# License: GPLv3+
+#+end_src
# Input: arg1 path input wikicode file
# Output: files wikicode file tree
# Depends: Bash 5.1.16, GNU Coreutils 8.32
-# Version: 0.4.0
+# Version: 0.5.0
re_sp='^(<!-- @subpage:)(.*)([ ]*-->)$'; # subpage marker pattern
d_out=./wikicode/; # default output dir
# Initialize subpage list wikicode file
must touch "$p_splwc";
- printf "==Stats==\n\n==Subpages==\n" >> "$p_splwc";
+ printf "==Stats==\n* Author:\n* Publication date:\n* [[/Combined]]\n\n==Subpages==\n" >> "$p_splwc";
# Read content files according to subpage list file
# Note: $i corresponds to “next” line ($lnext). Therefore, use
#!/bin/bash
# Desc:Marks the time when a remote server can be pinged.
# Depends: GNU Coreutils 8.32 (date, sleep), iputils-ping 3:20211215-1 (ping)
-# Version: 0.0.2
+# Version: 0.1.0
delay=10;
domain="google.com"
+yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
+die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
+
if [[ -n "$1" ]]; then domain="$1"; fi;
SECONDS=0;
printf "%s:STATUS:Starting ping...\n" "$(date -Is)";
-while ! ping -c1 "$domain"; do
- sleep "$delay";
+while [[ ! noPing == "true" ]]; do
+ printf "%s:" "$(date -Is)"; # prepend line with date
+ ping -c1 "$domain"; pingExitCode="$?"; # perform ping
+
+ if [[ "$pingExitCode" -eq 0 ]]; then
+ # Case if ping succeeded
+ printf "%s:Ping resolved after $SECONDS seconds.\n" "$(date -Is)";
+ exit 0;
+ elif [[ "$pingExitCode" -eq 1 ]]; then
+ sleep "$delay";
+ continue;
+ else
+ die "FATAL:Unknown error.";
+ exit 1;
+ fi;
done;
-printf "%s:Ping resolved after $SECONDS seconds.\n" "$(date -Is)";
-exit 0;
+
+yell "ERROR:Here be dragons.";
+exit 1;