#!/bin/bash
################################################################################
#
# bak2disc - backup to disc volumes while maintaining original data structure
# Copyright (C) 2005-2006 dorphell <dorphell [AT] gmail [DOT] com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
################################################################################
#--------------------------------------------------------------------
# PUBLIC CONSTANTS [Default Parameters]
#--------------------------------------------------------------------
## Dir used for meta-data (a few MBs of ASCII files) ##
TMP_DIR="${TEMP:-/tmp/bak2disc}"
mkdir -p $TMP_DIR
## Disc type (valid types: CD74, CD80, DVD5, DVD9, DLT7, LTO2, LTO3) ##
MEDIA_TYPE="DVD5"
## Space allocated for index metadata (MiB)##
INDEX_SIZE=4
## mkisofs options used by growisofs ##
MKISOFS_OPTS=" -r -J "
## Limit for the volume-filling search in the element array ##
SEARCH_RANGE=150
Label="Volume"
#--------------------------------------------------------------------
# PRIVATE CONSTANTS [Do not Modify]
#--------------------------------------------------------------------
VERSION="0.7-tpb"
PROG_NAME="bak2disc"
GB=1073741824 # 1024^3
MB=1048576 # 1024^2
## ANSI Color modifiers ##
C_BOLD="\e[1m" # Bold
C_NORM="\e[m\e[0;39m" # Normal
C_BLUE="\e[1;34m" # Blue
C_RED="\e[1;31m" # Red
## Only use newlines for field separation ##
IFS=$'\n'
## Error Messages ##
ErrorMsgs=(
"00: No error"
"01: Unknown error"
"02: Program \'\$2\' not in \\\$PATH"
"03: Working directory \'\$2\' already exists"
"04: Permission denied or file/directory does not exist: \$2"
"05: File[s] too big, choose a higher-capacity disc or suppress oversized file[s]"
"06: Temporary directory \'\$2\' exists"
"07: Could not create temporary directory \'\$2\'"
"08: User reported failed burn for disc volume \$2, --resume to try again"
"09: Option \'\$2\' requires an argument"
"10: Invalid option: \$2"
"11: Previous session metadata not found. Incorrect --temp parameter?"
"12: No options given, what do you want to do?"
"13: No \'--include\' files/directories defined"
"14: Disc \$2 index larger than allocated space, increase --index size"
"15: Please provide a single valid operating mode"
"16: Unknown disc type \'\$2\'. Valid types: cD74, CD80, DVD5, DVD9, DLT7, LTO2, LTO3"
"17: SIGINT caught"
"18: Invalid --speed argument, value must be an integer"
"19: mkisofs is really genisoimage which will not work")
#--------------------------------------------------------------------
# FUNCTIONS
#--------------------------------------------------------------------
Help() {
cat << EOF
$PROG_NAME v$VERSION (c) 2006 dorphell
Usage: $PROG_NAME <mode> [options]
Backup to disc volumes while maintaining original data structure
Informative flags:
-h, --help Print help screen
-v, --version Print version information
Operating mode flags: (one required)
-f, --fresh Start a new backup session
-n, --noburn Generate backup volume information but don't burn to disc
-r, --resume Resume the burn phase of a previous backup session (relies
on original metadata)
-w, --wipe Clean up temporary directory and exit
Accessibility flags:
-j, --eject Open drive tray for disc loading/unloading and skip the
verification prompt.
-l, --exlarge Automatically exclude files too large for backup media
-c, --nocolor Turn off all text color/highlighting
Configuration options: (every option requires an argument)
-i, --include Colon-separated file/directory paths to include (multiple
definitions and bash globbing wildcards are also vallid)
-e, --exclude File/directory paths to exclude (same syntax as --include)
-t, --temp Temporary directory [default: $TMP_DIR]
-o, --mkisofs Burning options passed onto mkisofs/growisofs
[default: $MKISOFS_OPTS]
-m, --mtype Disc type (CD74, CD80, DVD5, DVD9, DLT7, LTO2, LTO3) [default: $MEDIA_TYPE]
-x, --index Space allocated for index metadata out of disc capacity
[default: $INDEX_SIZE]
-g, --range Number of files/directories to poll when filling slack
space on volumes [default: $SEARCH_RANGE]
-s, --speed Speed factor of the writing process (integer value)
[default: Maximum supported by the drive]
--label Label the .iso and volume name
Examples:
$PROG_NAME --fresh --include "/etc:/mnt/HD*:/opt" -d /dev/hdc --mtype DVD5
$PROG_NAME -n -i /usr -i /var -e /var/log --temp /tmp --range 10 -m DVD5
$PROG_NAME --resume --temp /var/tmp
GNUtar:
gtar cf <tape> -T $TMP_DIR/Volume_1
EOF
}
Version() {
echo "$PROG_NAME $VERSION"
}
## ErrorExit "int error_code" "string reference_name" ##
ErrorExit() {
echo -ne "$C_BLUE" >&2
echo -ne ">> "
echo -ne "$C_RED" >&2
eval echo -n "ERROR ${ErrorMsgs[$1]}"
echo -ne "$C_NORM" >&2
echo
exit $1
}
## PrintBold "string message" ##
PrintBold() {
echo -ne "$C_BOLD" >&2
echo -ne "$1"
echo -ne "$C_NORM" >&2
}
## PrintStatus "string message" ##
PrintStatus() {
echo -ne "$C_BLUE" >&2
echo -ne ">>"
echo -ne "$C_NORM$C_BOLD " >&2
echo -ne "$1"
echo -ne "$C_NORM" >&2
echo
}
## YesNo "string question" "boolean default" [y/n] ##
YesNo() {
OPTIONS="[y/n]"
[ "$2" == "y" ] && OPTIONS="[Y/n] "
[ "$2" == "n" ] && OPTIONS="[y/N] "
PrintBold "$1 $OPTIONS"
IFS=$' \t\n' read ANSWER
[ ! "$ANSWER" ] && [ "$2" ] && ANSWER="$2"
while [ "$ANSWER" != 'y' ] && [ "$ANSWER" != 'n' ] && [ "$ANSWER" != 'Y' ] && [ "$ANSWER" != 'N' ]; do
PrintBold "Invalid response, please answer 'y' or 'n': "
IFS=$' \t\n' read ANSWER
done
[[ "$ANSWER" == 'y' || "$ANSWER" == 'Y' ]] && return 0 || return 1
}
## CheckPath "string program_name" ##
CheckPath() {
while [ "$1" ]; do
! type "$1" &>/dev/null && ErrorExit 2 "$1"
shift
done
}
## ParseArgs "string args" (e.g. "$@") ##
ParseArgs() {
while [ "$1" ]; do
## Informative flags ##
case "$1" in
-h|--help)
Help; exit ;;
-v|--version)
Version; exit ;;
## Operating modes flags ##
-f|--fresh)
FRESH=1; shift ;;
-r|--resume)
RESUME=1; shift ;;
-n|--noburn)
NOBURN=1; shift ;;
-w|--wipe)
WIPE=1; shift ;;
## Accessibility flags ##
-j|--eject)
CheckPath 'eject'
EJECT=1; shift ;;
-l|--exlarge)
AUTO_EXCLUDE=1; shift ;;
-c|--nocolor)
NOCOLOR=1; shift ;;
## Configuration options ##
-i|--include)
[ ! "$2" ] && ErrorExit 9 "$1"
INCLUDE="$INCLUDE:$2"; shift 2;;
-e|--exclude)
[ ! "$2" ] && ErrorExit 9 "$1"
EXCLUDE="$EXCLUDE:$2"; shift 2;;
-o|--mkisofs)
[ ! "$2" ] && ErrorExit 9 "$1"
MKISOFS_OPTS="$2"; shift 2;;
-m|--mtype)
[ ! "$2" ] && ErrorExit 9 "$1"
MEDIA_TYPE="$2"; shift 2;;
-x|--index)
[ ! "$2" ] && ErrorExit 9 "$1"
INDEX_SIZE="$2"; shift 2;;
-t|--temp)
[ ! "$2" ] && ErrorExit 9 "$1"
TMP_DIR="$2"; shift 2;;
-g|--range)
[ ! "$2" ] && ErrorExit 9 "$1"
SEARCH_RANGE="$2"; shift 2;;
-s|--speed)
[ ! "$2" ] && ErrorExit 9 "$1"
[ "${2##*[^0-9]*}" ] || ErrorExit 18
SPEED="-speed=$2"; shift 2;;
--label)
[ ! "$2" ] && ErrorExit 9 "$1"
Label="$2"; shift 2;;
*)
Help; ErrorExit 10 "$1";;
esac
done
}
## SetMediaSize "string preset" (e.g. SetMediaSize "dvd9") ##
SetMediaSize() {
MEDIA_TYPE="$(echo $1| tr a-z A-Z)"
case "$MEDIA_TYPE" in
CD74) MEDIA_SIZE=650 ;;
CD80) MEDIA_SIZE=703 ;;
DVD5) MEDIA_SIZE=4482 ;;
DVD9) MEDIA_SIZE=8144 ;;
DLT7) MEDIA_SIZE=30000 ;;
LTO2) MEDIA_SIZE=190000 ;;
LTO2c) MEDIA_SIZE=323000 ;;
LTO3) MEDIA_SIZE=390000;;
LTO3c) MEDIA_SIZE=663000;;
*) Help;
ErrorExit 16 "$1" ;;
esac
let "MEDIA_SIZE-=INDEX_SIZE"
}
## ValidatePath "string path" "string output_variable" ##
## If path is readable, return its proper pathname; else error + exit ##
ValidatePath() {
[ ! -r "$1" ] && CleanUp && ErrorExit 4 "$1"
[ "$1" == '/' ] && return
eval "$2=\"$(echo "$1"| sed 's|/\+|/|g;s|/$||')\""
}
## GetList "string du_output_syntax" (e.g. "1234 <TAB> /path/to/dir") ##
## Returns a list of files/dirs that are less than media size ##
GetList() {
## Set Size and Name ##
VARS=(${1//$'\t'/$'\n'})
Size=${VARS[0]}
Name=${VARS[1]}
if [ $Size -gt $((MEDIA_SIZE*MB)) ] && [ -d "$Name" ]; then
for x in $($DU -ba --max-depth=1 "$Name"| gawk -F '\t' '$2 != "'$Name'" {print}'); do
GetList "$x"
done
else
printf "%s\t%s\n" "$Name" "$Size"
fi
}
## Burn disc volumes defined in TMP_DIR ##
BurnVolumes() {
NumOfDiscs=$(head -n 1 "$TMP_DIR/summary" 2>/dev/null| gawk '{print $8}')
MEDIA_TYPE=$(head -n 1 "$TMP_DIR/summary" 2>/dev/null| gawk '{print $9}')
## Check if metadata exists ##
[ ! $NumOfDiscs ] && ErrorExit 11
## If --resume, reprint distribution summary ##
if [ $RESUME ]; then
PrintStatus "Resuming burn session..."
while read line; do
vol=$(echo $line| gawk '$1 == "Disc" {printf "%i\n", $2}')
[ ${line:0:1} == " " ] && echo "$line" && continue
[ ${line:0:1} == "I" ] && PrintStatus "$line" && continue
[ -z $vol ] && PrintBold "$line\n" && continue
[ -e "$TMP_DIR/Volume_$vol" ] && PrintBold "$line\n" || echo "$line [Done]"
done < "$TMP_DIR/summary"
echo
fi
## Make ISO files
# for (( DISC_NUM=1; DISC_NUM<=$NumOfDiscs; DISC_NUM++ )); do
DISC_NUM=1
while [ $DISC_NUM -le $NumOfDiscs ]; do
## Volume already burned ##
[ ! -e "$TMP_DIR/Volume_$DISC_NUM" ] && continue
## Burn the volume ##
ALL_MKISOFS_OPTS="$MKISOFS_OPTS -quiet -V ${Label}-${DISC_NUM}_of_$NumOfDiscs -graft-points -exclude-list $EXC_LIST -path-list $TMP_DIR/Volume_$DISC_NUM -o ${Label}_$DISC_NUM.iso"
IFS=$' \n';
echo "mkisofs $ALL_MKISOFS_OPTS"
mkisofs $ALL_MKISOFS_OPTS
IFS=$'\n'
## Volume successfully burned, delete volume metadata ##
rm "$TMP_DIR/Volume_$DISC_NUM" "$TMP_DIR/volume_${DISC_NUM}_of_${NumOfDiscs}"
DISC_NUM=$(expr $DISC_NUM + 1)
done
## Backup complete, wipe out metadata ##
PrintStatus "All $NumOfDiscs backup volumes burned."
CleanUp
}
## CleanUp (removes "$TMP_DIR" entirely) ##
CleanUp() {
PrintStatus "Cleaning up temporary data"
rm -rf "$TMP_DIR"
}
Terminate() {
echo
ErrorExit 17
}
#--------------------------------------------------------------------
# SCRIPT START
#--------------------------------------------------------------------
## Capture ^C exit code ##
trap Terminate SIGINT
## Check if utilities are in $PATH ##
# Solaris /bin/du won't work. Look for GNU du named gdu
[ -f $(which gdu) ] && DU=$(which gdu) || DU=$(which du)
[ $(uname -s) == "SunOS" -a $(basename $DU) != "gdu" ] && ErrorExit 2 "gdu"
CheckPath 'gawk' 'sed' 'printf' 'sort' "$DU" 'stat' 'comm' 'mkisofs'
mkisofs --version | grep -s genisoimage > /dev/null
[ $? -eq 0 ] && echo "mkisofs is really genisoimage which will not work"
## Parse command-line arguments ##
[ -z "$1" ] && Help && ErrorExit 12
ParseArgs "$@"
ValidatePath "$TMP_DIR" "TMP_DIR"
TMP_DIR="$TMP_DIR/$PROG_NAME-$USER"
FILE_LIST="$TMP_DIR/include"
EXC_LIST="$TMP_DIR/exclude"
SetMediaSize "$MEDIA_TYPE"
[ $NOCOLOR ] && unset C_BOLD C_NORM C_BLUE C_RED
## No operating modes defined, error ##
[ $((FRESH+NOBURN+RESUME+WIPE)) -ne 1 ] && Help && ErrorExit 15
## If --resume specified, just burn using preexisting metadata ##
[ $RESUME ] && BurnVolumes && exit
## Delete any garbage/leftovers and start fresh ##
[ $WIPE ] && CleanUp && exit
## Check for leftovers, if not clean, ask what to do ##
if [ -e "$TMP_DIR" ]; then
! YesNo "Leftover metadata detected; DELETE and start fresh?" "n" && PrintBold "Nothing dnoe... exiting\n" && exit
CleanUp
fi
## Check/Ask for required variables ##
[ ! "$INCLUDE" ] && Help && ErrorExit 13
PrintBold "$C_RED-------------------------------------------------------------------$C_NORM\n"
PrintBold " Do not modify included files until they have been written to disc\n"
PrintBold " Excessive growth may cause volume to overflow disc capacity\n"
PrintBold "$C_RED-------------------------------------------------------------------$C_NORM\n"
## Start a fresh backup now ##
mkdir -p "$TMP_DIR" || ErrorExit 7 "$TMP_DIR"
## Convert path lists to arrays ##
INCLUDE=(${INCLUDE//:/$'\n'})
EXCLUDE=(${EXCLUDE//:/$'\n'})
## Validate all dir/file paths ##
x=0
while [ $x -lt ${#INCLUDE[@]} ]; do ValidatePath "${INCLUDE[$x]}" "INCLUDE[$x]"; x=$(expr $x + 1); done
x=0
while [ $x -lt ${#EXCLUDE[@]} ]; do ValidatePath "${EXCLUDE[$x]}" "EXCLUDE[$x]"; x=$(expr $x + 1); done
## Remove all dupes ##
for x in "${INCLUDE[@]}"; do INCLUDE=($(echo "${INCLUDE[*]}"| sed "\|^$x/|d"| sort -u)); done
for x in "${EXCLUDE[@]}"; do EXCLUDE=($(echo "${EXCLUDE[*]}"| sed "\|^$x/|d"| sort -u)); done
## Generate element filelist from INCLUDE paths ##
for x in "${INCLUDE[@]}"; do
GetList "$($DU -bs "$x")"
done| sort > "$FILE_LIST"
## Remove excluded items from filelist ##
if [ "${EXCLUDE[*]}" ]; then
for item in $($DU -bs "${EXCLUDE[@]}"); do
item=(${item//$'\t'/$'\n'})
Size=${item[0]}
Name=${item[1]}
## *Exact* match ##
Exists=$(gawk -F '\t' '$1 == "'$Name'" || $1 ~ "'$Name'/" {print $1}' "$FILE_LIST")
if [ "$Exists" ]; then
for x in $Exists; do sed "\|^$x\t.*|d" -i "$FILE_LIST"; done
else
Parent=""
while [ ! "$Parent" ] && [ "$Name" ]; do
Name="${Name%/*}"
Parent=$(gawk -F '\t' '$1 == "'$Name'" {print}' "$FILE_LIST")
done
Parent=(${Parent//$'\t'/$'\n'})
PName=${Parent[0]}
PSize=${Parent[1]}
NewSize=$((PSize-Size))
sed "s|\(^$PName\)\t\(.*$\)|\1\t$NewSize|" -i "$FILE_LIST"
fi
done
fi
## Initialize element array ##
ELEMENTS=($(cat "$FILE_LIST"))
## Fill content elements into disc volumes ##
Current=0; Count=0; CountRange=0; declare -i Size; LastElement=${#ELEMENTS[@]}
while [ "${ELEMENTS[*]}" ]; do
line=(${ELEMENTS[$Count]//$'\t'/$'\n'})
Name="${line[0]}" # File name
Size="${line[1]}" # File size
if [ $Size -gt $((MEDIA_SIZE*MB)) ]; then # file bigger than disc capacity
AEXCLUDE[${#AEXCLUDE[@]}]="$Name" # add file to auto-exclude list
# unset ELEMENTS[$Count] Name
unset ELEMENTS[$Count]
unset Name
fi
if [ ! $Name ] && [ $Count -ne $CountRange ]; then # skip null elements
:
elif [ $CountRange -ne 0 ] && [ $Count -eq $CountRange ]; then # end of search range, volume filled
CountRange=0
let "Count=KeepCount-1" # go to 1st element that didn't fit
let "Current++"
# echo "$Current"
# echo "$((VolSizes[$Current]+Size)) $((MEDIA_SIZE*MB))"
elif [ $((VolSizes[$Current]+Size)) -lt $((MEDIA_SIZE*MB)) ]; then
VolSizes[$Current]=$((${VolSizes[$Current]}+$Size))
VolNames[$Current]="${VolNames[$Current]}$Name\n"
unset ELEMENTS[$Count]
else # element too big for current vol
if [ $CountRange -eq 0 ]; then # remember element position
KeepCount=$Count
let "CountRange=Count+SEARCH_RANGE"
if [ $CountRange -gt $LastElement ]; then # don't set range outside the array!
CountRange=$LastElement
fi
fi
fi
let "Count++"
done
## Ask if big files should be auto-excluded ##
if [ "$AEXCLUDE" ]; then
if [ ! $AUTO_EXCLUDE ]; then
for x in "${AEXCLUDE[@]}"; do echo "| $x"; done
YesNo "+ The preceding file[s] will not fit on a $MEDIA_TYPE disc, exclude and continue?" "y" || ErrorExit 5
echo
fi
EXCLUDE=("${EXCLUDE[@]}" "${AEXCLUDE[@]}")
fi
## Account for excluded files in distribution summary ##
find "${EXCLUDE[@]}" ! -type d 2>/dev/null| sort > "$EXC_LIST"
## Generate index and filelists ##
x=0;
while [ $x -lt ${#VolNames[@]} ]; do
BurnName="Volume_$((x+1))" # e.g. Volume_1
IndexName="volume_$((x+1))_of_${#VolNames[@]}" # e.g. volume_1_of_16
## Generate mkisofs graft-points formated filelist ##
echo -e "${VolNames[$x]}"| gawk -F '\n' '$1 {printf "data%s=%s\n", $1, $1}' > "$TMP_DIR/$BurnName"
## Generate volume reference index ##
VolFiles[$x]=$(comm -23 <(find $(echo -e "${VolNames[$x]}") ! -type d 2>/dev/null| sort) "$EXC_LIST")
echo "${VolFiles[$x]}" > "$TMP_DIR/$IndexName"
## Generate master catalog ##
echo "### $IndexName ###" >> "$TMP_DIR/catalog.idx"
echo -e "${VolFiles[$x]}\n"| sed 's|^/|'$((x+1))': /|' >> "$TMP_DIR/catalog.idx"
## Append reference index and master catalog to mkisofs input filelist ##
#echo "$IndexName=$TMP_DIR/$IndexName" >> "$TMP_DIR/$BurnName"
echo "catalog.idx=$TMP_DIR/catalog.idx" >> "$TMP_DIR/$BurnName"
x=$(expr $x + 1 )
done
## Generate mkisofs exclude list file ##
echo "${EXCLUDE[*]}" > "$EXC_LIST"
TotalSize=$(echo "${VolSizes[*]}"| gawk '{sum+=$1} END {printf "%.2f", (sum/'$GB') }')
Index_Size=$(stat -c %s "$TMP_DIR/catalog.idx" 2>/dev/null)
TotalFiles=$(echo "${VolFiles[*]}"| grep -c "[^\n]")
NumOfDiscs=${#VolNames[@]}
## Overall backup summary ##
SUM_TOTALS=$(printf "Summary: %s files (%s GiB) divided into %s %s disc volumes" "$TotalFiles" "$TotalSize" "$NumOfDiscs" "$MEDIA_TYPE")
SUM_INC=$(for x in "${INCLUDE[@]}"; do echo " $x"; done)
SUM_EXC=$(for x in "${EXCLUDE[@]}"; do echo " $x"; done)
PrintBold "$SUM_TOTALS\n"; echo -e "$SUM_TOTALS" > "$TMP_DIR/summary"
PrintStatus "Items Included:" && echo "$SUM_INC" && echo -e "Items Included:\n$SUM_INC" >> "$TMP_DIR/summary"
[ $EXCLUDE ] && PrintStatus "Items Excluded:" && echo "$SUM_EXC" && echo -e "Items Excluded:\n$SUM_EXC" >> "$TMP_DIR/summary"
## Disc volume distribution summary ##
x=0
while [ $x -lt $NumOfDiscs ]; do
DISC_NUM=$((x+1))
DISC_FILES=$(echo "${VolFiles[$x]}"| grep -c "[^\n]")
VIDX_SIZE=$(stat -c %s "$TMP_DIR/volume_${DISC_NUM}_of_${NumOfDiscs}")
DISC_SIZE=$(echo "${VolSizes[$x]}" $Index_Size $VIDX_SIZE $MB| gawk '{printf "%f", ($1+$2+$3)/$4 }')
DISC_FREE=$(echo $MEDIA_SIZE $INDEX_SIZE $DISC_SIZE| gawk '{printf "%i", $1+$2-$3}')
PRINT_DIST="$PRINT_DIST$(printf "Disc %3d: %5d files -> %8.2f MiB, %4i MiB free" "$DISC_NUM" "$DISC_FILES" "$DISC_SIZE" "$DISC_FREE")\n"
[ $DISC_FREE -lt 1 ] && ErrorExit 14 $DISC_NUM
x=$(expr $x + 1 )
done; PrintBold $PRINT_DIST
## Save distribution summary ##
echo -ne $PRINT_DIST >> "$TMP_DIR/summary"
## If --noburn specified, exit now ##
[ $NOBURN ] && PrintStatus "Backup metadata generated." && exit
## Ask whether to burn now or leave metadata for later ##
YesNo "\nBegin burn sequence now?" "y" && BurnVolumes
#--------------------------------------------------------------------
# SCRIPT END
#--------------------------------------------------------------------
Wednesday, July 29, 2009
Archiving a tree to DVD with bak2disc
bak2disc by dorphell is a script to create DVDs of a directory tree, preserving the structure. It will create an index file on the DVD so you can find which DVD the files are on.
I modified the script to create .iso files. You can also feed the file lists created to tar. So I modified the script to create lists contining X GB of data. I feed that to tar and can tar files to a DLT, SDLT, LTO, etc tape.
I sent an email and didn't get a reply. I'll try to get a version up somewhere.
I modified the script to create .iso files. You can also feed the file lists created to tar. So I modified the script to create lists contining X GB of data. I feed that to tar and can tar files to a DLT, SDLT, LTO, etc tape.
I sent an email and didn't get a reply. I'll try to get a version up somewhere.
Wednesday, June 11, 2008
Micro Irrigation
Article showing typical layout
HOWTO install a system
From Colorado State
RainBird automation
Tutorials
Irrigo systems - nice picture
Drip Works - end user vendor
Toro Micro Irrigation
HOWTO install a system
From Colorado State
RainBird automation
Tutorials
Irrigo systems - nice picture
Drip Works - end user vendor
Toro Micro Irrigation
Wednesday, June 4, 2008
Gardening
Just a few quick sites
Getting rid of weeds from http://www.thisgardenisillegal.com
Composting
http://myfolia.com/ is a garden tracking journal
According to http://www.garden.org, We are Zone 6a. And they have a nice plant zone finder.
Oh My!! GardenMon
Getting rid of weeds from http://www.thisgardenisillegal.com
Composting
http://myfolia.com/ is a garden tracking journal
According to http://www.garden.org, We are Zone 6a. And they have a nice plant zone finder.
Oh My!! GardenMon
Friday, February 8, 2008
Unsolicited phone calls
From Slashdot:
Here is an effective (though laborious) way to deal with that.
1. Register on National Do-Not-Call list.
2. Wait 3 month beginning period.
3. Get caller ID.
4. Wait for another call.
5. Be pleasant to the person, if you can order something cheap, say $10, do it.
6. Get their address and phone number as you place the order.
7. Photograph the Caller ID display as evidence.
8. Take good notes including date, time, person talked to, company name, as more evidence.
9. Copy the bill you receive for $10 as conclusive evidence of marketing intent.
10. Go to your county courthouse, lodge a small claim for $500 for a telemarketing violation.
11. Send them proper notice they are being sued.
12. Since they are often out of state, they won't show and you get default judgment.
13. If they do show, you have proof of listing, notice, call, and call purpose.
14. For bonus dollars, ($500 per item) look into whether they have,
train to, practice and publish upon demand the required company calling
policies.
15. Profit!!!
Powered by ScribeFire.
Sunday, February 3, 2008
Podcasting with an M-Audio Microtrack
Think of the MT (Microtrack) as you would a cassette recorder. Don't worry about listening. That's for later on the computer. The MT is to capture the sound. Much you'd use a camera to take lots of pictures of an event. You'll select relevant photos for your presentation, possibly editing and cleaning them up. You might change the order of the photos to better fit your presentation.
Make sure the battery is charged up.
Use the electret microphone on the wire, not the T mic. This lets you put the microphone near the sound.
On one side of the MT (microtrack) is a L/M/H switch. Put it on M for Microphone.
Put the microphone in its jack.
Press record to start recording. Do a test recording to check sound levels.
On the screen you'll see 2 bars, labeled L and R, for Left and Right.
The levels are the sensitivity of the sound. You want to adjust the level or sensitivity of the microphone so you get all the sound but not so sensitive that the sound is distorted.
Too low a level & the mic will not pickup (hear) any sound. Too high a level and there will be too much static and distortion. You might be able to hear someone's heartbeat ;-)
You want to adjust the levels so they are near the right side, but not hitting the end. Read your script while doing this until the levels are adjusted.
Hit record again to stop the recording. The MT will display "Writing" as it saves the recording as an MP3 file.
I'd suggest keeping a list of what you record:
Now that you've recorded, bring the MT over to the computer. Plug the USB cable into the MT and the computer.
The MT will appear as a disk called "MICRODRIVE" with all your recordings named file001.mp3, file002.mp3, etc. There is one for each time you pressed rec to start & then rec to end. Your log will help you figure out which is which.
They might not start number 001, but they will be numbered sequentially.
Create a folder in your My Documents folder and copy the files from the MICRODRIVE into it. Do not erase them from the MICRODRIVE yet. These are your originals. Some people make a CD of them so they have a read only copy.
Now you have your sound files to edit. MT supplies Audacity which is a good choice. You can copy it from the CD or download it off the internet.
I've never used Audacity, but basically it lets you edit your sound files. You can filter it to change the sound if your original recording wasn't optimal. Mostly, you'll be cutting out dead air and splicing snippets into place. You might find splicing the 1st half of take #2 with the 2nd half of take #3 to be the best choice. The better your original, the less to do latter.
Make sure the battery is charged up.
Use the electret microphone on the wire, not the T mic. This lets you put the microphone near the sound.
On one side of the MT (microtrack) is a L/M/H switch. Put it on M for Microphone.
Put the microphone in its jack.
Press record to start recording. Do a test recording to check sound levels.
On the screen you'll see 2 bars, labeled L and R, for Left and Right.
The levels are the sensitivity of the sound. You want to adjust the level or sensitivity of the microphone so you get all the sound but not so sensitive that the sound is distorted.
Too low a level & the mic will not pickup (hear) any sound. Too high a level and there will be too much static and distortion. You might be able to hear someone's heartbeat ;-)
You want to adjust the levels so they are near the right side, but not hitting the end. Read your script while doing this until the levels are adjusted.
Hit record again to stop the recording. The MT will display "Writing" as it saves the recording as an MP3 file.
I'd suggest keeping a list of what you record:
- Sound check
- Script take #1
- Script take #2
- recording of speech to students
Now that you've recorded, bring the MT over to the computer. Plug the USB cable into the MT and the computer.
The MT will appear as a disk called "MICRODRIVE" with all your recordings named file001.mp3, file002.mp3, etc. There is one for each time you pressed rec to start & then rec to end. Your log will help you figure out which is which.
They might not start number 001, but they will be numbered sequentially.
Create a folder in your My Documents folder and copy the files from the MICRODRIVE into it. Do not erase them from the MICRODRIVE yet. These are your originals. Some people make a CD of them so they have a read only copy.
Now you have your sound files to edit. MT supplies Audacity which is a good choice. You can copy it from the CD or download it off the internet.
I've never used Audacity, but basically it lets you edit your sound files. You can filter it to change the sound if your original recording wasn't optimal. Mostly, you'll be cutting out dead air and splicing snippets into place. You might find splicing the 1st half of take #2 with the 2nd half of take #3 to be the best choice. The better your original, the less to do latter.
Tuesday, January 15, 2008
Subscribe to:
Posts (Atom)