Miscellaneous Scripts
The following are various Bash scripts I have written over the years, hosted here on the off chance somebody might find them useful. Most of these were written up as a quick fix for whatever problem I was tackling at the moment, rather than full on projects. As such, they are not well tested or as throughly thought out as most of my other software.You can download any of these files from the Downloads section, just make sure to make them executable after download with "chmod +x".
2Pass.sh
I wrote this script up when a friend needed a bunch of videos re-encoded and their own computer wasn't up to the task (not if he wanted it finished within the year, anyway). This isn't terribly flexible as it is only setup to work with XviD and you have to set the desired bitrate in the file itself. XviD has fallen out of favor for newer codecs now, but the script itself is still a useful example if you want to wrap up a different encoder.#!/bin/sh
# 2Pass.sh
APPNAME="2Pass"
VER="1.0"
# Simple script to do a two pass XviD encode on given file. Can also encode all
# files in current directory.
# Set bitrate for final video
RATE=6000
#------------------------------------------------------------------------------#
ErrorMsg ()
{
# ErrorMsg
# Displays either a minor (warning) or critical error, exiting on an critical.
# If message starts with "n", a newline is printed before message.
[[ $(expr substr "$2" 1 1) == "n" ]] && echo
if [ "$1" == "ERR" ]; then
# This is a critical error, game over.
echo " ERROR: ${2#n}"
exit 1
elif [ "$1" == "WRN" ]; then
# This is only a warning, script continues but may not work fully.
echo " WARNING: ${2#n}"
fi
}
VerifyCmd ()
{
# VerifyCmd
archive.sh
This was written as a quick experiment when I was putting together Mainframe. The idea was to export a directory over NFS or Samba, and run this script against it every day or so. The script scans the directory for files and compresses every file that isn't already compressed. This would allow me to have an "Archive" share that would compress anything which was put into it, perfect for long-term storage of files. In the end I never put it into use, but the concept is sound.#!/bin/sh
#
# Script to scan a directory for files, and compress them if they haven't
# already been.
# Compression, gzip and bzip2 supported
COMP="bzip2"
# Delete files after compression (BE CAREFUL)
DELFILE="yes"
# Make sure we have a target
[ "$1" == "" ] && echo "Must give target!" && exit
# Determine compression type and extension
if [ "$COMP" == "gzip" ]; then
COMPEXT="gz"
elif [ "$COMP" == "bzip2" ]; then
COMPEXT="bz2"
else
echo "Unsupported compression type!"
exit
fi
# Create the list of files to work with
LIST=`find $1 -type f`
# Search for files
for i in $LIST;
do
if [ `echo $i | awk -F . '{print $NF}'` != "$COMPEXT" ]; then
echo -n "Compressing $i..."
gzip -c9 $i > $i.$COMPEXT
echo "OK!"
[ "$DELFILE" == "yes" ] && rm -f $i
fi
done
gpstime.sh
This is a very simple little script that I wrote as an experiment, for which I intended on basing a full project on. I never went through with the project (yet), but the idea seems to work well enough.Basically, the idea was to set the system time from a GPS device connected over Bluetooth. The Bluetooth GPS must already be connected with RFCOMM (check out the Bluetooth Hacking Primer for information on setting up RFCOMM links under Linux) before running this script, which simply parses the output and sets the system time once it is downloaded from the satellites.
There are a lot of problems with this idea, unfortunately. First off, the GPS device will report the time from it's own internal RTC until it has received a time update from the satellites. The problem is that the GPS has no reliable way of indicating when this occurs, so some additional checking would be necessary to make sure you weren't setting your system time to a cheap RTC. There is also additional latency inherent with using Bluetooth as the communication medium, which causes more drift than if the device was connected over USB. Finally, the only way to get truly accurate time updates from serial devices (emulated serial, or otherwise) is to use Pulse Per Second (PPS), which the Linux kernel doesn't actually have built-in support for. Though even if it did, the RFCOMM emulated serial device wouldn't be able to communicate PPS to the kernel anyway.
So in other words, this is a very rough way to set the time from GPS. It isn't terribly accurate, but in my testing did appear to be at least as accurate as setting the system time with NTP when taking Internet/network latency into account.
#!/bin/sh
# Hackish way to set system time to GPS PPS
# Pre-fetch date info
DATE="$(date +%m%d)"
YEAR="$(date +%y)"
# Pause and return UTC time string as close to PPS as possible:
UTC="$(awk -F, '/\$GPGGA/ {print $2; exit}' /dev/rfcomm0 | cut -c 1-6)"
TIME="$(echo $UTC | cut -c 1-4)"
SECONDS="$(echo $UTC | cut -c 5-6)"
# Put it back together and set the time
date -u $DATE$TIME$YEAR.$SECONDS
web_ftp.sh
This one is actually used by DigiFAIL itself to generate the files used by the "Download" UI. Basically, it creates a hidden metadata file for each file in a given directory (MD5, size, date), then combines those into an HTML page which can be served out via your HTTP daemon of choice.Common Functions
Early in my Bash scripting career, I realized I was writing the same code over and over again way too often. In more advanced programming languages, commonly used functions are always broken out into their own subroutines so you don't have to keep putting it in manually, but it seemed most people didn't necessarily do the same with Bash scripts. Maybe it is just because I take some of these scripts pretty far into the realm of "Should have done it with C", but I like to think it is better to just get them written out properly in the first place, and paste them into new projects I am working on.Indeed, most of the scripts I have posted up on the site make use of these functions in some way or another, so I figured it was worth putting them up on their own.
ErrorMsg
I use this one a lot. It is a function to display either a warning or critical error message, with an error message causing the script to exit. You can also have the message printed with or without a newline.ErrorMsg ()
{
# ErrorMsg
# Displays either a minor (warning) or critical error, exiting on an critical.
# If message starts with "n", a newline is printed before message.
[[ $(expr substr "$2" 1 1) == "n" ]] && echo
if [ "$1" == "ERR" ]; then
# This is a critical error, game over.
echo " ERROR: ${2#n}"
exit 1
elif [ "$1" == "WRN" ]; then
# This is only a warning, script continues but may not work fully.
echo " WARNING: ${2#n}"
fi
}
Using ErrorMsg is pretty straight forward, you simply call the function with
the type of error, and put the message you want printed in quotes. Now using
the newline function might not be immediately obvious. The idea there is that
you might want to print an "OK" type message on the same line as a command if
it succeeds, and an error if it doesn't. Let's look at the following example
code:
# Let's look at a warning:
echo "I am warning you..."
ErrorMsg WRN "You have been warned!"
# Here we check for a file on the system that should exist:
echo -n "Checking for /etc/exports..."
[ -f /etc/exports ] || \
ErrorMsg ERR "nFile: /ext/exports does not exist!"
echo "OK!"
# Now let's look for something you (probably...) don't have, to see the error:
echo -n "Checking for ~/nudez..."
[ -d ~/nudez ] || \
ErrorMsg ERR "nFailed to locate the nudez!!"
echo "OK!"
Looking at the output of the following lines, you can see how the output has a
nice clean look on success, while still maintaining a consistent visual style
on a warning or failure:
I am warning you...
WARNING: You have been warned!
Checking for /etc/exports...OK!
Checking for ~/nudez...
ERROR: Failed to locate the nudez!!
VerifyCmd
VerifyCmd is not strictly necessary, you could just check for the presence of the file using a regular Bash conditional and then call ErrorMsg accordingly; but I wanted to have a little nicer way to tell the user what is going on, and make it very clear they are missing a program rather than showing a general failure message, especially if it is not a required program.VerifyCmd ()
{
# VerifyCmd
If you want to use VerifyCmd to just check for the program rather than
outputting it's usual message (like if you wanted to show a different message
with ErrorMsg), you can call it with the boolean "0" to turn off visual output.


