#!/bin/bash # Graph animation of input data DEBUG=1 VERBOSE=0 X=( \| / - \\ ) CONTAINER=mp4 err() { printf "$0[error]: %s\n" "$*" >&2; exit 2; } warn() { printf "$0[warning]: %s\n" "$*" >&2; } debug() { ((DEBUG)) && printf "$0[debug]: %s\n" "$*" >&2; } verbose() { ((VERBOSE)) && printf "$0[info]: %s\n" "$*" >&2; } vprintf() { ((VERBOSE)) && printf "$@" >&2; } help() { printf '%s\n' " Usage: $0 [-v] [-c ext] datafile... $0 -h -v ... verbose -c ext ... container extension -h ... this help "; } while getopts hvc: opt do case $opt in h) help; exit 0;; v) ((VERBOSE++));; c) CONTAINER=$OPTARG;; \?) help >&2; exit 1;; esac done shift $(( OPTIND-1 )) tmp=$( mktemp -d ) || err "Cannot create temporary directory" trap 'debug "Cleanup"; rm -rf "$tmp"' EXIT debug "Temporary directory: $tmp" if [ $# -eq 0 ] then help >&2 err "Datafile missing" fi for data do [ -f "$data" ] || err "File '$data' does not exist" [ -r "$data" ] || err "File '$data' is not readable" [ -s "$data" ] || err "File '$data' is empty" egrep -v '^-?[0-9]*\.?[0-9]+$' "$data" && err "Bad '$data' format" lines=$( wc -l < "$data" ) digits=${#lines} range=$( sort -n "$data" | sed -n '1h;${H;g;s/\n/:/p}' ) # Prepare separate frames # For each frame vprintf "$0[verbose]: Done " for (( i=1; i<=lines; i++ )) do # Prepare data # Run gnuplot to make single frame (( p=100*i/lines )) vprintf '\b\b\b\b\b\b%s %3d%%' "${X[i%4]}" "$p" { cat <<-GP set terminal png set output "$tmp/$( printf "%0${digits}d.png" $i )" plot [0:$lines][$range] '-' with lines GP head -n "$i" "$data" } | gnuplot done # Join frames into animation ffmpeg -y -i "$tmp/%0${digits}d.png" "$data.$CONTAINER" done