├── AllFiles.tgz
├── tinyscript.sh
├── 087-remotebackup-filelist
├── alice.txt.gz
├── long-words.txt.gz
├── big-word-list.txt.gz
├── 019-locate.sh
├── 070-yahoo-search.html
├── 075-page-with-counter.html
├── 031-numberlines.sh
├── 009-scriptbc.sh
├── 019-mklocatedb.sh
├── 008-echon.sh
├── 023-remindme.sh
├── 023-remember.sh
├── 060-bbcnews.sh
├── 075-streamfile.cgi
├── 075-updatecounter.sh
├── palindrome.sh
├── 017-logrm.sh
├── 033-toolong.sh
├── 014-nfmt.sh
├── 041-diskspace.sh
├── 074-guestbook.txt
├── 035-mysftp.sh
├── 069-showcgienv.sh
├── 025-checkspelling.sh
├── 096-titleterm.sh
├── text.snippet.txt
├── 039-fquota.sh
├── 067-getstock.sh
├── 070-logsearch.cgi
├── 087-trimmailbox.sh
├── 076-ssi-sample.html
├── 062-define.sh
├── ragged.txt
├── 014-ragged.txt
├── 014-ragged.txt.shp
├── 013-hilow.sh
├── how-many-commands.sh
├── 091-watch-and-nice.sh
├── README.md
├── 072-contactus.html
├── 076-randomquote.sh
├── 002-validalnum.sh
├── 097-itunelist.sh
├── 054-docron.sh
├── 058-connecttime.sh
├── 034-quota.sh
├── 048-fixguest.sh
├── 059-ftpget.sh
├── 080-htpasswd-b.pl
├── 082-ftpsyncdown.sh
├── 032-showfile.sh
├── 072-contactus.cgi
├── 067-portfolio.sh
├── 042-newdf.sh
├── 063-weather.sh
├── 012-library-test.sh
├── 077-checklinks.sh
├── 027-spelldict.sh
├── 051-enabled.sh
├── 061-getlinks.sh
├── 071-getdope.sh
├── 085-enginehits.sh
├── 050-set-date.sh
├── 073-photoalbum.cgi
├── 018-formatdir.sh
├── 029-loancalc.sh
├── 049-findsuid.sh
├── 095-addmacalias.sh
├── 071-kevin-and-kell.cgi
├── 024-calc.sh
├── 090-getstats.sh
├── state.capitals.txt
├── 093-listmacusers.sh
├── 030-agenda.sh
├── 083-ssync.sh
├── 021-findman.sh
├── 066-getexchrate.sh
├── 010-filelock.sh
├── 043-slocate.sh
├── 020-DIR.sh
├── 057-archivedir.sh
├── 079-webspell.sh
├── 040-diskhogs.sh
├── 075-counter.sh
├── 044-adduser.sh
├── 085-searchinfo.sh
├── 011-colors.sh
├── 065-moviedata.sh
├── 083-sftpsync.sh
├── 003-normdate.sh
├── 028-convertatemp.sh
├── 081-ftpsyncup.sh
├── 080-apm-footer.html
├── 005-validint.sh
├── 101-states.sh
├── 098-open2.sh
├── 087-remotebackup.sh
├── 036-cgrep.sh
├── 001-inpath.sh
├── 045-suspenduser.sh
├── 015-newrm.sh
├── 043-mkslocate.sh
├── sample.crontab
├── 037-zcat.sh
├── 006-validfloat.sh
├── 064-checklibrary.sh
├── 084-webaccess.sh
├── 046-deleteuser.sh
├── 078-checkexternal.sh
├── 056-backup.sh
├── 004-nicenumber.sh
├── 038-bestcompress.sh
├── 052-killall.sh
├── 066-exchangerate.sh
├── 091-renicename.sh
├── 099-unscramble.sh
├── 088-unpacker.sh
├── 094-addmacuser.sh
├── 013-guessword.sh
├── 086-weberrors.sh
├── 068-changetrack.sh
├── 007-valid-date.sh
├── 030-addagenda.sh
├── 047-validator.sh
├── 055-rotatelogs.sh
├── 100-hangman.sh
├── 074-guestbook.cgi
├── 089-xferlog.sh
├── 022-timein.sh
├── 016-unrm.sh
├── 026-shpell.sh
├── 092-addvirtual.sh
├── 090-netperf.sh
├── 053-verifycron.sh
├── 080-apm.cgi
└── 012-library.sh
/AllFiles.tgz:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tinyscript.sh:
--------------------------------------------------------------------------------
1 | test=2
2 |
--------------------------------------------------------------------------------
/087-remotebackup-filelist:
--------------------------------------------------------------------------------
1 | *.sh
2 | *.html
3 |
--------------------------------------------------------------------------------
/alice.txt.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/epety/100-shell-script-examples/HEAD/alice.txt.gz
--------------------------------------------------------------------------------
/long-words.txt.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/epety/100-shell-script-examples/HEAD/long-words.txt.gz
--------------------------------------------------------------------------------
/big-word-list.txt.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/epety/100-shell-script-examples/HEAD/big-word-list.txt.gz
--------------------------------------------------------------------------------
/019-locate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # locate - search the locate database for the specified pattern
4 |
5 | locatedb="/var/locate.db"
6 |
7 | exec grep -i "$@" $locatedb
8 |
--------------------------------------------------------------------------------
/070-yahoo-search.html:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/075-page-with-counter.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sample Web Page with Counter Substitution
4 | This page has been visited ---countervalue--- times,
5 | and you must therefore be visitor
6 | ---countervalue---
7 | out of
8 | ---countervalue---
9 | visitors!
10 |
11 |
12 |
--------------------------------------------------------------------------------
/031-numberlines.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # numberlines - a simple alternative to cat -n, etc
4 |
5 | for filename
6 | do
7 | linecount="1"
8 | (while read line
9 | do
10 | echo "${linecount}: $line"
11 | linecount="$(( $linecount + 1 ))"
12 | done) < $filename
13 | done
14 |
15 | exit 0
16 |
--------------------------------------------------------------------------------
/009-scriptbc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # scriptbc - wrapper for 'bc' that returns the value of a formula
4 |
5 | if [ $1 = "-p" ] ; then
6 | precision=$2
7 | shift 2
8 | else
9 | precision=2 # default
10 | fi
11 |
12 | bc -q -l << EOF
13 | scale=$precision
14 | $*
15 | quit
16 | EOF
17 |
18 | exit 0
19 |
--------------------------------------------------------------------------------
/019-mklocatedb.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # mklocatedb - build the locate database using find. Must be root to run this
4 |
5 | locatedb="/var/locate.db"
6 |
7 | if [ "$(whoami)" != "root" ] ; then
8 | echo "Must be root to run this command." >&2
9 | exit 1
10 | fi
11 |
12 | find / -print > $locatedb
13 |
14 | exit 0
15 |
--------------------------------------------------------------------------------
/008-echon.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # echon - a script to emulate the -n flag functionality with 'echo'
4 | # for Unix systems that don't have that available.
5 |
6 | echon()
7 | {
8 | echo "$*" | tr -d '\n'
9 | }
10 |
11 | echon "this is a test: "
12 | read answer
13 |
14 | echon this is a test too " "
15 | read answer2
16 |
--------------------------------------------------------------------------------
/023-remindme.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # remindme - search a datafile for matching lines, or show the contents
4 | # of the datafile if no arg is specified
5 |
6 | rememberfile="$HOME/.remember"
7 |
8 | if [ $# -eq 0 ] ; then
9 | more $rememberfile
10 | else
11 | grep -i "$@" $rememberfile | ${PAGER:-more}
12 | fi
13 |
14 | exit 0
15 |
--------------------------------------------------------------------------------
/023-remember.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # remember - an easy command-line based memory pad
4 | # search the results with 'remindme'
5 |
6 | rememberfile="$HOME/.remember"
7 |
8 | if [ $# -eq 0 ] ; then
9 | echo "Enter note, end with ^D: "
10 | cat - >> $rememberfile
11 | else
12 | echo "$@" >> $rememberfile
13 | fi
14 |
15 | exit 0
16 |
--------------------------------------------------------------------------------
/060-bbcnews.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # bbcnews - report the top stories on the BBC World Service
4 |
5 | url="http://news.bbc.co.uk/2/low/technology/default.stm"
6 |
7 | lynx -source $url | \
8 | sed -n '/Last Updated:/,/newssearch.bbc.co.uk/p' | \
9 | sed 's/\
10 | />\
11 | /g' | \
12 | grep -v -E '(<|>)' | \
13 | fmt | \
14 | uniq
15 |
--------------------------------------------------------------------------------
/075-streamfile.cgi:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # streamfile - output an HTML file, replacing the sequence
4 | # ---countervalue--- with the current counter value.
5 |
6 | infile="page-with-counter.html"
7 | counter="./counter.cgi"
8 |
9 | echo "Content-type: text/html"
10 | echo ""
11 |
12 | value="$(counter)"
13 |
14 | sed "s/---countervalue---/$value/g" < $infile
15 |
16 | exit 0
17 |
--------------------------------------------------------------------------------
/075-updatecounter.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # updatecounter - a tiny script that updates the counter file to
4 | # the value specified. Assumes that locking is done elsewhere.
5 |
6 | if [ $# -ne 1 ] ; then
7 | echo "Usage: $0 countfile"; exit 1
8 | fi
9 |
10 | count="$(cat $1)"
11 | newcount="$(( ${count:-0} + 1 ))"
12 |
13 | echo "$newcount" > $1
14 | chmod a+rw $1
15 |
16 | exit 0
17 |
18 |
--------------------------------------------------------------------------------
/palindrome.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # specify palindrome possibility as args
4 |
5 | if [ $# -eq 0 ] ; then
6 | echo Usage: $0 possible palindrome >&2
7 | exit 1
8 | fi
9 |
10 | testit="$(echo $@ | sed 's/[^[:alpha:]]//g' | tr '[:upper:]' '[:lower:]')"
11 | backwards="$(echo $testit | rev)"
12 |
13 | if [ "$testit" = "$backwards" ] ; then
14 | echo "$@ is a palindrome"
15 | else
16 | echo "$@ is not a palindrome"
17 | fi
18 |
19 | exit 0
20 |
--------------------------------------------------------------------------------
/017-logrm.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # logrm - log all file deletion requests unless "-s" flag is used
3 |
4 | removelog="/tmp/removelog.log"
5 |
6 | if [ $# -eq 0 ] ; then
7 | echo "Usage: $0 [-s] list of files or directories" >&2
8 | exit 1
9 | fi
10 |
11 | if [ "$1" = "-s" ] ; then
12 | # silent operation requested... don't log
13 | shift
14 | else
15 | echo "$(date): ${USER}: $@" >> $removelog
16 | fi
17 |
18 | /bin/rm "$@"
19 |
20 | exit 0
21 |
--------------------------------------------------------------------------------
/033-toolong.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # toolong - only feed the fmt command those lines in the input stream
3 | # that are longer than the specified length
4 |
5 | width=72
6 |
7 | if [ ! -r "$1" ] ; then
8 | echo "Usage: $0 filename" >&2; exit 1
9 | fi
10 |
11 | while read input
12 | do
13 | if [ ${#input} -gt $width ] ; then
14 | echo "$input" | fmt
15 | else
16 | echo "$input"
17 | fi
18 | done < $1
19 |
20 | exit 0
21 |
22 |
--------------------------------------------------------------------------------
/014-nfmt.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # nfmt - A version of fmt, using nroff. Adds two useful flags: -w X for
4 | # line width and -h to enable hyphenation for better fills.
5 |
6 | while getopts "hw:" opt; do
7 | case $opt in
8 | h ) hyph=1 ;;
9 | w ) width="$OPTARG" ;;
10 | esac
11 | done
12 | shift $(($OPTIND - 1))
13 |
14 | nroff << EOF
15 | .ll ${width:-72}
16 | .na
17 | .hy ${hyph:-0}
18 | .pl 1
19 | $(cat "$@")
20 | EOF
21 |
22 | exit 0
23 |
--------------------------------------------------------------------------------
/041-diskspace.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # diskspace - summarize available disk space and present in a logical
4 | # and readable fashion
5 |
6 | tempfile="/tmp/available.$$"
7 |
8 | trap "rm -f $tempfile" EXIT
9 |
10 | cat << 'EOF' > $tempfile
11 | { sum += $4 }
12 | END { mb = sum / 1024
13 | gb = mb / 1024
14 | printf "%.0f MB (%.2fGB) of available disk space\n", mb, gb
15 | }
16 | EOF
17 |
18 | df -k | awk -f $tempfile
19 |
20 | exit 0
21 |
--------------------------------------------------------------------------------
/074-guestbook.txt:
--------------------------------------------------------------------------------
1 | Sat Sep 6 14:57:02 MST 2003|Lucas Gonze|lucas@gonze.com|I very much enjoyed my stay at your web site. Best of luck.
2 | Sat Sep 6 22:54:49 MST 2003|Dee-Ann LeBlanc|dee@renaissoft.com|Kinda plain, but that's better than it being covered in animations and flaming text. :)
3 | Sun Sep 7 02:50:48 MST 2003|MC|null@mcslp.com|I don't want the world, I just want your half.
4 | Tue Sep 9 02:34:48 MST 2003|Andrey Bronfin|andreyb@elrontelesoft.com|Nice to be here.
5 |
--------------------------------------------------------------------------------
/035-mysftp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # mysftp - make sftp start up more like ftp
4 |
5 | echo -n "User account: "
6 | read account
7 |
8 | if [ -z "$account" ] ; then
9 | exit 0; # changed their mind, presumably
10 | fi
11 |
12 | if [ -z "$1" ] ; then
13 | echo -n "Remote host: "
14 | read host
15 | if [ -z $host ] ; then
16 | exit 0
17 | fi
18 | else
19 | host=$1
20 | fi
21 |
22 | # echo sftp -C $account@$host
23 |
24 | exec /usr/bin/sftp -C $account@$host
25 |
--------------------------------------------------------------------------------
/069-showcgienv.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # show CGI env - display the CGI runtime environment, as given to any
4 | # CGI script on this system.
5 |
6 | echo "Content-type: text/html"
7 | echo ""
8 |
9 | # now the real information
10 |
11 | echo "CGI Runtime Environment
"
12 | echo ""
13 | env || printenv
14 | echo "
"
15 | echo "Input stream is:
"
16 | echo ""
17 | cat -
18 | echo "(end of input stream)
"
19 |
20 | exit 0
21 |
--------------------------------------------------------------------------------
/025-checkspelling.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # checkspelling - check the spelling of a word
4 |
5 | spell="ispell -l" # if you have ispell installed instead
6 | # if not, just define spell=spell or
7 | # equivalent.
8 |
9 | if [ $# -lt 1 ] ; then
10 | echo "Usage: $0 word or words" >&2
11 | exit 1
12 | fi
13 |
14 | for word
15 | do
16 | if [ -z $(echo $word | $spell) ] ; then
17 | echo "$word: spelled correctly."
18 | else
19 | echo "$word: misspelled."
20 | fi
21 | done
22 |
23 | exit 0
24 |
--------------------------------------------------------------------------------
/096-titleterm.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | # titleterm - tell the Mac OS X Terminal application to change its name
4 | # to the value specified as an argument to this succinct script.
5 |
6 | # To use this to show your current working directory, for example:
7 | # alias precmd 'titleterm "$PWD"' [tcsh]
8 | # or
9 | # export PROMPT_COMMAND="titleterm \"\$PWD\"" [bash]
10 |
11 | if [ $# -eq 0 ]; then
12 | echo "Usage: $0 title" >&2
13 | exit 1
14 | else
15 | echo -ne "\033]0;$1\007"
16 | fi
17 |
18 | exit 0
19 |
--------------------------------------------------------------------------------
/text.snippet.txt:
--------------------------------------------------------------------------------
1 | Perhaps one of the most valuable uses of shell scripts is to fix
2 | your particular flavor of Unix and make it more like other flavors,
3 | to bring your commands into conformance or to increase consistency
4 | across different systems. The outsider view of Unix suggests a
5 | nice, uniform command-line experience, helped along by the existence
6 | and compliance with the POSIX standards for Unix, but anyone who's
7 | ever touched more than one computer knows how much they can vary
8 | within these broad parameters.
9 |
--------------------------------------------------------------------------------
/039-fquota.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # FQUOTA - Disk quota analysis tool for Unix.
4 | # Assumes that all user accounts are >= UID 100.
5 |
6 | MAXDISKUSAGE=20
7 |
8 | for name in $(cut -d: -f1,3 /etc/passwd | awk -F: '$2 > 99 { print $1 }')
9 | do
10 | echo -n "User $name exceeds disk quota. Disk usage is: "
11 |
12 | find / /usr /var /Users -user $name -xdev -type f -ls | \
13 | awk '{ sum += $7 } END { print sum / (1024*1024) " Mbytes" }'
14 |
15 | done | awk "\$9 > $MAXDISKUSAGE { print \$0 }"
16 |
17 | exit 0
18 |
19 |
--------------------------------------------------------------------------------
/067-getstock.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # getstock - given a stock ticker symbol, return its current value
4 | # from the Lycos web site
5 |
6 | url="http://finance.lycos.com/qc/stocks/quotes.aspx?symbols="
7 |
8 | if [ $# -ne 1 ] ; then
9 | echo "Usage: $(basename $0) stocksymbol" >&2
10 | exit 1
11 | fi
12 |
13 | value="$(lynx -dump "$url$1" | grep 'Last price:' | \
14 | awk -F: 'NF > 1 && $(NF) != "N/A" { print $(NF) }')"
15 |
16 | if [ -z $value ] ; then
17 | echo "error: no value found for ticker symbol $1." >&2
18 | exit 1
19 | fi
20 |
21 | echo $value
22 |
23 | exit 0
24 |
--------------------------------------------------------------------------------
/070-logsearch.cgi:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # log Yahoo! search - given a search request, log the pattern, then
4 | # feed the entire sequence to the real Yahoo search system.
5 |
6 | logfile="/home/taylor/scripts/searchlog.txt"
7 |
8 | if [ ! -f $logfile ] ; then
9 | touch $logfile
10 | chmod a+rw $logfile
11 | fi
12 |
13 | if [ -w $logfile ] ; then
14 | echo "$(date): $QUERY_STRING" | sed 's/p=//g;s/+/ /g' >> $logfile
15 | fi
16 |
17 | # echo "Content-type: text/html"
18 | # echo ""
19 |
20 | echo "Location: http://search.yahoo.com/bin/search?$QUERY_STRING"
21 | echo ""
22 |
23 | exit 0
24 |
--------------------------------------------------------------------------------
/087-trimmailbox.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # trimmailbox - a simple script to ensure that only the four most recent
4 | # messages remain in the users mailbox. Works with Berkeley Mail
5 | # (aka Mailx or mail): will need modifications for other mailers!!
6 |
7 | keep=4 # by default, let's just keep around the four most recent messages
8 |
9 | totalmsgs="$(echo 'x' | mail | sed -n '2p' | awk '{print $2}')"
10 |
11 | if [ $totalmsgs -lt $keep ] ; then
12 | exit 0 # nothing to do
13 | fi
14 |
15 | topmsg="$(( $totalmsgs - $keep ))"
16 |
17 | mail > /dev/null << EOF
18 | d1-$topmsg
19 | q
20 | EOF
21 |
22 | exit 0
23 |
--------------------------------------------------------------------------------
/076-ssi-sample.html:
--------------------------------------------------------------------------------
1 |
2 | Server side include demonstration
3 |
4 | Server-side include demonstration page
5 | You are visitor
6 |
8 | to this site.
9 |
10 | This page was last modified on
11 |
12 | according to the SSI LAST_MODIFIED variable.
13 |
14 | Finally, the random tagline for this load is:
15 |
16 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/062-define.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # define - given a word, return its definition from dictionary.com
4 |
5 | url="http://www.cogsci.princeton.edu/cgi-bin/webwn2.0?stage=1&word="
6 |
7 | if [ $# -ne 1 ] ; then
8 | echo "Usage: $0 word" >&2
9 | exit 1
10 | fi
11 |
12 | lynx -source "$url$1" | \
13 | grep -E '(^[[:digit:]]+\.| has [[:digit:]]+$)' | \
14 | sed 's/<[^>]*>//g' |
15 | ( while read line
16 | do
17 | if [ "${line:0:3}" = "The" ] ; then
18 | part="$(echo $line | awk '{print $2}')"
19 | echo ""
20 | echo "The $part $1:"
21 | else
22 | echo "$line" | fmt | sed 's/^/ /g'
23 | fi
24 | done
25 | )
26 |
27 | exit 0
28 |
--------------------------------------------------------------------------------
/ragged.txt:
--------------------------------------------------------------------------------
1 | So she sat on, with closed eyes, and half believed herself in
2 | Wonderland, though she knew she had but to open them again, and
3 | all would change to dull reality--the grass would be only rustling
4 | in the wind, and the pool rippling to the waving of the reeds--the
5 | rattling teacups would change to tinkling sheep-bells, and the
6 | Queen's shrill cries to the voice of the shepherd boy--and the
7 | sneeze of the baby, the shriek of the Gryphon, and all the other
8 | queer noises, would change (she knew) to the confused clamour of
9 | the busy farm-yard--while the lowing of the cattle in the distance
10 | would take the place of the Mock Turtle's heavy sobs.
11 |
--------------------------------------------------------------------------------
/014-ragged.txt:
--------------------------------------------------------------------------------
1 | So she sat on, with closed eyes, and half believed herrself in
2 | Wonderland, though she knew she had but to open them again, and
3 | all would change to dull reality--the grass would be only rustling in the wind, and the pool rippling to the waving of the reeds--the
4 | rattling teacups would change to tinkling sheep- bells, and the
5 | Queen's shrill cries to the voice of the shepherd boy--and the
6 | sneeze
7 | of the baby, the shriek of the Gryphon, and all thy other queer noises, would change (she knew)
8 | to the confused clamour of the busy farm-yard--while the lowing of
9 | the cattle in
10 | the distance would take the place of the Mock Turtle's heavy sobs.
11 |
--------------------------------------------------------------------------------
/014-ragged.txt.shp:
--------------------------------------------------------------------------------
1 | So she sat on, with closed eyes, and half believed herrself in
2 | Wonderland, though she knew she had but to open them again, and
3 | all would change to dull reality--the grass would be only rustling in the wind, and the pool reippling to the waving of the reeds--the
4 | rattling teacups would change to tinkling sheep- bells, and the
5 | Queen's shrill cries to the voice of the shepherd boy--and the
6 | sneeze
7 | of the baby, the shriek of the Gryphon, and all thy other queer noises, would change (she knew)
8 | to the confused clamour of the busy farm-yard--while the lowing of
9 | the cattle in
10 | the distance would take the place of the Mock Turtle's heavy sobs.
11 |
--------------------------------------------------------------------------------
/013-hilow.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # hilow - a simple number guessing game
3 |
4 | biggest=100 # maximum number possible
5 | guess=0 # guessed by player
6 | guesses=0 # number of guesses made
7 | number=$(( $$ % $biggest )) # random number, 1 .. $biggest
8 |
9 | while [ $guess -ne $number ] ; do
10 | echo -n "Guess? " ; read guess
11 | if [ "$guess" -lt $number ] ; then
12 | echo "... bigger!"
13 | elif [ "$guess" -gt $number ] ; then
14 | echo "... smaller!"
15 | fi
16 | guesses=$(( $guesses + 1 ))
17 | done
18 |
19 | echo "Right!! Guessed $number in $guesses guesses."
20 |
21 | exit 0
22 |
--------------------------------------------------------------------------------
/how-many-commands.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # how many commands: a simple script to count how many executable commands
4 | # are in your current PATH.
5 |
6 | myPATH="$(echo $PATH | sed -e 's/ /~~/g' -e 's/:/ /g')"
7 | count=0 ; nonex=0
8 |
9 | for dirname in $myPATH ; do
10 | directory="$(echo $dirname | sed 's/~~/ /g')"
11 | if [ -d "$directory" ] ; then
12 | for command in $(ls "$directory") ; do
13 | if [ -x "$directory/$command" ] ; then
14 | count="$(( $count + 1 ))"
15 | else
16 | nonex="$(( $nonex + 1 ))"
17 | fi
18 | done
19 | fi
20 | done
21 |
22 | echo "$count commands, and $nonex entires that weren't marked executable"
23 |
24 | exit 0
25 |
--------------------------------------------------------------------------------
/091-watch-and-nice.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # watch and nice - watch for the specified process name, and renice
4 | # to the desired value when seen
5 |
6 | renicename="$HOME/bin/renicename"
7 |
8 | if [ $# -ne 2 ] ; then
9 | echo "Usage: $(basename $0) desirednice jobname" >&2
10 | exit 1
11 | fi
12 |
13 | pid="$($renicename -p "$2")"
14 |
15 | if [ ! -z "$(echo $pid | sed 's/[0-9]*//g')" ] ; then
16 | echo "Failed to make a unique match in the process table for $2" >&2
17 | exit 1
18 | fi
19 |
20 | currentnice="$(ps -lp $pid | tail -1 | awk '{print $6}')"
21 |
22 | if [ $1 -gt $currentnice ] ; then
23 | echo "Adjusting priority of $2 to $1"
24 | renice $1 $pid
25 | fi
26 |
27 | exit 0
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 100 shell script examples
2 | ====================================
3 |
4 | This is archive of shell scripts that i found on the interenet long time ago. I'm not the author. Original website is located here: http://intuitive.com/wicked/wicked-cool-shell-script-library.shtml (author wrote a [book](http://intuitive.com/wicked/index.shtml)).
5 |
6 | Besides this, you can check out these repos too:
7 | - https://code.google.com/p/bsc/
8 | - https://code.google.com/p/bashscripts/
9 | - https://github.com/onlyshk/bash-snippets
10 |
11 |
12 |
13 | Also, there is an interesting article about this that links many shell script examples:
14 | - http://dberkholz.com/2011/04/07/bash-shell-scripting-libraries/
--------------------------------------------------------------------------------
/072-contactus.html:
--------------------------------------------------------------------------------
1 |
2 | contact us!
3 |
4 |
13 | And this is an example sentence with a werd or two misspelled, for the
14 | webspell script (script #84).
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/076-randomquote.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # randomquote - given a one-line-per-entry datafile, this
4 | # script will randomly pick one and display it. Best used
5 | # as an SSI call within a Web page.
6 |
7 | awkscript="/tmp/randomquote.awk.$$"
8 |
9 | if [ $# -ne 1 ] ; then
10 | echo "Usage: randomquote datafilename" >&2
11 | exit 1
12 | elif [ ! -r "$1" ] ; then
13 | echo "Error: quote file $1 is missing or not readable" >&2
14 | exit 1
15 | fi
16 |
17 | trap "/bin/rm -f $awkscript" 0
18 |
19 | cat << "EOF" > $awkscript
20 | BEGIN { srand(); }
21 | { s[NR] = $0 }
22 | END { print s[randint(NR)] }
23 | function randint(n) { return int (n * rand() ) + 1 }
24 | EOF
25 |
26 | awk -f $awkscript < "$1"
27 |
28 | exit 0
29 |
--------------------------------------------------------------------------------
/002-validalnum.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # validalAlphaNum - Ensures that input only consists of alphabetical
3 | # and numeric characters.
4 |
5 | validAlphaNum()
6 | {
7 | # validate arg: returns 0 if all upper+lower+digits, 1 otherwise
8 |
9 | # Remove all unacceptable chars
10 | compressed="$(echo $1 | sed -e 's/[^[:alnum:]]//g')"
11 |
12 | if [ "$compressed" != "$input" ] ; then
13 | return 1
14 | else
15 | return 0
16 | fi
17 | }
18 |
19 | # Sample usage of this function in a script
20 |
21 | echo -n "Enter input: "
22 | read input
23 |
24 | if ! validAlphaNum "$input" ; then
25 | echo "Your input must consist of only letters and numbers." >&2
26 | exit 1
27 | else
28 | echo "Input is valid."
29 | fi
30 |
31 | exit 0
32 |
--------------------------------------------------------------------------------
/097-itunelist.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # itunelist - list your iTunes library in a succinct and attractive
4 | # manner, suitable for sharing with others and using (with diff)
5 | # to ensure that you have synchronized iTune libraries on different
6 | # computers and laptops.
7 |
8 | itunehome="$HOME/Music/iTunes"
9 | ituneconfig="$itunehome/iTunes Music Library.xml"
10 |
11 | musiclib="/$(grep '>Music Folder<' "$ituneconfig" | cut -d/ -f5- | \
12 | cut -d\< -f1 | sed 's/%20/ /g')"
13 |
14 | echo Your music library is at $musiclib
15 |
16 | if [ ! -d "$musiclib" ] ; then
17 | echo "$0: Confused: Music library $musiclib isn't a directory?" >&2
18 | exit 1
19 | fi
20 |
21 | exec find "$musiclib" -type d -mindepth 2 -maxdepth 2 \! -name '.*' -print | sed "s|$musiclib/||"
22 |
--------------------------------------------------------------------------------
/054-docron.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # DOCRON - simple script to run the daily, weekly and monthly
4 | # system cron jobs on a system where it's likely that
5 | # it'll be shut down at the usual time of day when
6 | # this would occur.
7 |
8 | rootcron="/etc/crontab"
9 |
10 | if [ $# -ne 1 ] ; then
11 | echo "Usage: $0 [daily|weekly|monthly]" >&2
12 | exit 1
13 | fi
14 |
15 | if [ "$(id -u)" -ne 0 ] ; then
16 | echo "$0: Command must be run as 'root'" >&2
17 | exit 1
18 | fi
19 |
20 | job="$(awk "NR > 6 && /$1/ { for (i=7;i<=NF;i++) print \$i }" $rootcron)"
21 |
22 | if [ -z $job ] ; then
23 | echo "$0: Error: no $1 job found in $rootcron" >&2
24 | exit 1
25 | fi
26 |
27 | SHELL=/bin/sh # to be consistent with cron's default
28 |
29 | eval $job
30 |
--------------------------------------------------------------------------------
/058-connecttime.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # connecttime - reports cumulative connection time for month/year entries
4 | # found in the system log file.
5 |
6 | log="/var/log/system.log"
7 | tempfile="/tmp/$0.$$"
8 |
9 | trap "rm $tempfile" 0
10 |
11 | cat << 'EOF' > $tempfile
12 | BEGIN {
13 | lastmonth=""; sum = 0
14 | }
15 | {
16 | if ( $1 != lastmonth && lastmonth != "" ) {
17 | if (sum > 60) { total = sum/60 " hours" }
18 | else { total = sum " minutes" }
19 | print lastmonth ": " total
20 | sum=0
21 | }
22 | lastmonth=$1
23 | sum += $8
24 | }
25 | END {
26 | if (sum > 60) { total = sum/60 " hours" }
27 | else { total = sum " minutes" }
28 | print lastmonth ": " total
29 | }
30 | EOF
31 |
32 | grep "Connect time" $log | awk -f $tempfile
33 |
34 | exit 0
35 |
--------------------------------------------------------------------------------
/034-quota.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # newquota - a front-end to quota that works with fullword flags a la GNU
3 |
4 | # quota has three possible flags: -g, -v and -q and in this script
5 | # we allow them to be '--group' '--verbose' and '--quiet' too:
6 |
7 | flags=""
8 | realquota="/usr/bin/quota"
9 |
10 | while [ $# -gt 0 ]
11 | do
12 | echo checking flag $1
13 | case $1
14 | in
15 | --help ) echo "Usage: $0 [--group --verbose --quiet -gvq]" >&2
16 | exit 1 ;;
17 | --group | -group) flags="$flags -g"; shift ;;
18 | --verbose | -verbose) flags="$flags -v"; shift ;;
19 | --quiet | -quiet) flags="$flags -q"; shift ;;
20 | -- ) shift; break ;;
21 | * ) break; # done with 'while' loop!
22 | esac
23 | done
24 |
25 | exec $realquota $flags "$@"
26 |
--------------------------------------------------------------------------------
/048-fixguest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # fixguest - Clean up the guest account during the logout process
4 |
5 | # don't trust environment variables: reference read-only sources
6 |
7 | iam="$(whoami)"
8 | myhome="$(grep "^${iam}:" /etc/passwd | cut -d: -f6)"
9 |
10 | # *** Do NOT run this script on a regular user account!
11 |
12 | if [ "$iam" != "guest" ] ; then
13 | echo "Error: you really don't want to run fixguest on this account." >&2
14 | exit 1
15 | fi
16 |
17 | if [ ! -d $myhome/..template ] ; then
18 | echo "$0: no template directory found for rebuilding." >&2
19 | exit 1
20 | fi
21 |
22 | # remove all files and directories in the home account
23 |
24 | cd $myhome
25 |
26 | rm -rf * $(find . -name ".[a-zA-Z0-9]*" -print)
27 |
28 | # now the only thing present should be the ..template directory
29 |
30 | cp -Rp ..template/* .
31 |
32 | exit 0
33 |
--------------------------------------------------------------------------------
/059-ftpget.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # ftpget - given an ftp: style URL, unwrap it, and try to obtain the file
4 | # using anonymous ftp.
5 |
6 | anonpass="$LOGNAME@$(hostname)"
7 |
8 | if [ $# -ne 1 ] ; then
9 | echo "Usage: $0 ftp://..." >&2
10 | exit 1
11 | fi
12 |
13 | # Typical URL: ftp://ftp.ncftp.com/2.7.1/ncftpd-2.7.1.tar.gz
14 |
15 | if [ "$(echo $1 | cut -c1-6)" != "ftp://" ] ; then
16 | echo "$0: Malformed url. I need it to start with ftp://" >&2;
17 | exit 1
18 | fi
19 |
20 | server="$(echo $1 | cut -d/ -f3)"
21 | filename="$(echo $1 | cut -d/ -f4-)"
22 | basefile="$(basename $filename)"
23 |
24 | echo ${0}: Downloading $basefile from server $server
25 |
26 | ftp -n << EOF
27 | open $server
28 | user ftp $anonpass
29 | get $filename $basefile
30 | quit
31 | EOF
32 |
33 | if [ $? -eq 0 ] ; then
34 | ls -l $basefile
35 | fi
36 |
37 | exit 0
38 |
--------------------------------------------------------------------------------
/080-htpasswd-b.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | if (! scalar @ARGV ) {
4 | print "Usage: htpasswd-b passwordfile user password\n";
5 | print "(this program automatically creates the pw file if needed.)\n";
6 | exit 0;
7 | }
8 |
9 | @saltsource = ('a'..'z', 'A'..'Z', '0'..'9','.','/');
10 | $randum_num = int(rand(scalar @saltsource));
11 | $salt = $saltsource[$randum_num];
12 | $randum_num = int(rand(scalar @saltsource));
13 | $salt .= $saltsource[$randum_num];
14 |
15 | $outf=$ARGV[0];
16 | $user=$ARGV[1];
17 | $passwd=$ARGV[2];
18 |
19 | if ($user && $passwd) {
20 | $encrypted = crypt($passwd, "$salt");
21 |
22 | if (-f $outf) {
23 | open(OUT, ">>$outf") || die "htpasswd-b error: $!\n";
24 | } else {
25 | open(OUT, ">$outf") || die "htpasswd-b error: $!\n";
26 | }
27 | print OUT "$user:$encrypted\n";
28 | close(OUT);
29 |
30 | exit 0;
31 | }
32 |
--------------------------------------------------------------------------------
/082-ftpsyncdown.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # ftpsyncdown - Given a source directory on a remote FTP server,
4 | # download all the files therein into the current directory.
5 |
6 | tempfile="/tmp/ftpsyncdown.$$"
7 |
8 | trap "/bin/rm -f $tempfile" 0 1 15 # zap tempfile on exit
9 |
10 | if [ $# -eq 0 ] ; then
11 | echo "Usage: $0 user@host { remotedir }" >&2
12 | exit 1
13 | fi
14 |
15 | user="$(echo $1 | cut -d@ -f1)"
16 | server="$(echo $1 | cut -d@ -f2)"
17 |
18 | echo "open $server" > $tempfile
19 | echo "user $user" >> $tempfile
20 |
21 | if [ $# -gt 1 ] ; then
22 | echo "cd $2" >> $tempfile
23 | fi
24 |
25 | cat << EOF >> $tempfile
26 | prompt
27 | mget *
28 | quit
29 | EOF
30 |
31 | echo "Synchronizing: Downloading files"
32 |
33 | if ! ftp -n < $tempfile ; then
34 | echo "Done. All files on $server downloaded to $(pwd)"
35 | fi
36 |
37 | exit 0
38 |
--------------------------------------------------------------------------------
/032-showfile.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # showfile - show the contents of a file, including additional useful info
3 |
4 | width=72
5 |
6 | for input
7 | do
8 | lines="$(wc -l < $input | sed 's/ //g')"
9 | chars="$(wc -c < $input | sed 's/ //g')"
10 | owner="$(ls -ld $input | awk '{print $3}')"
11 | echo "-----------------------------------------------------------------"
12 | echo "File $input ($lines lines, $chars characters, owned by $owner):"
13 | echo "-----------------------------------------------------------------"
14 | while read line
15 | do
16 | if [ ${#line} -gt $width ] ; then
17 | echo "$line" | fmt | sed -e '1s/^/ /' -e '2,$s/^/+ /'
18 | else
19 | echo " $line"
20 | fi
21 | done < $input
22 |
23 | echo "-----------------------------------------------------------------"
24 |
25 | done | more
26 |
27 | exit 0
28 |
--------------------------------------------------------------------------------
/072-contactus.cgi:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Process the contact us form data, email it to the designated
4 | # recipient, and return a succinct thank you message.
5 |
6 | recipient="taylor"
7 | thankyou="thankyou.html" # optional 'thanks' page
8 |
9 | ( cat << EOF
10 | From: (Your Web Site Contact Form) www@$(hostname)
11 | To: $recipient
12 | Subject: Contact Request from Web Site
13 |
14 | Content of the Web site contact form:
15 |
16 | EOF
17 |
18 | cat - | tr '&' '\n' | \
19 | sed -e 's/+/ /g' -e 's/%40/@/g' -e 's/=/: /'
20 |
21 | echo ""; echo ""
22 | echo "Form submitted on $(date)"
23 | ) | sendmail -t
24 |
25 | echo "Content-type: text/html"
26 | echo ""
27 |
28 | if [ -r $thankyou ] ; then
29 | cat $thankyou
30 | else
31 | echo ""
32 | echo "Thank you. We'll try to contact you soonest."
33 | echo ""
34 | fi
35 |
36 | exit 0
37 |
--------------------------------------------------------------------------------
/067-portfolio.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # portfolio - calculate the value of each stock in your holdings,
4 | # then calculate the value of your overall portfolio, based on
5 | # the latest stock market position.
6 |
7 | getstock="sh 069-getstock.sh"
8 | scriptbc="$HOME/bin/scriptbc"
9 | portfolio="$HOME/.portfolio"
10 |
11 | if [ ! -f $portfolio ] ; then
12 | echo "$(basename $0): No portfolio to check? ($portfolio)" >&2
13 | exit 1
14 | fi
15 |
16 | while read holding
17 | do
18 | eval $(echo $holding | \
19 | awk -F\| '{print "name=\""$1"\"; ticker=\""$2"\"; hold=\""$3"\""}')
20 | if [ ! -z "$ticker" ] ; then
21 | value="$(eval $getstock $ticker)"
22 | totval="$($scriptbc ${value:-0} \* $hold)"
23 | echo "$name is trading at $value (your $hold shares = $totval)"
24 | sumvalue="$($scriptbc ${sumvalue:-0} + $totval)"
25 | fi
26 | done < $portfolio
27 |
28 | echo "Total portfolio value: $sumvalue"
29 |
30 | exit 0
31 |
--------------------------------------------------------------------------------
/042-newdf.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # newdf - a friendlier version of df
4 |
5 | sedscript="/tmp/newdf.$$"
6 |
7 | trap "rm -f $sedscript" EXIT
8 |
9 | cat << 'EOF' > $sedscript
10 | function showunit(size)
11 | { mb = size / 1024; prettymb=(int(mb * 100)) / 100;
12 | gb = mb / 1024; prettygb=(int(gb * 100)) / 100;
13 |
14 | if ( substr(size,1,1) !~ "[0-9]" ||
15 | substr(size,2,1) !~ "[0-9]" ) { return size }
16 | else if ( mb < 1) { return size "K" }
17 | else if ( gb < 1) { return prettymb "M" }
18 | else { return prettygb "G" }
19 | }
20 |
21 | BEGIN {
22 | printf "%-27s %7s %7s %7s %8s %-s\n",
23 | "Filesystem", "Size", "Used", "Avail", "Capacity", "Mounted"
24 | }
25 |
26 | !/Filesystem/ {
27 |
28 | size=showunit($2);
29 | used=showunit($3);
30 | avail=showunit($4);
31 |
32 | printf "%-27s %7s %7s %7s %8s %-s\n",
33 | $1, size, used, avail, $5, $6
34 | }
35 | EOF
36 |
37 | df -k | awk -f $sedscript
38 |
39 | exit 0
40 |
--------------------------------------------------------------------------------
/063-weather.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # weather - report weather forecast, including lat/long, for zip
4 |
5 | llurl="http://www.census.gov/cgi-bin/gazetteer?city=&state=&zip="
6 | wxurl="http://wwwa.accuweather.com"
7 | wxurl="$wxurl/adcbin/public/local_index_print.asp?zipcode="
8 |
9 | if [ "$1" = "-a" ] ; then
10 | size=999; shift
11 | else
12 | size=5
13 | fi
14 |
15 | if [ $# -eq 0 ] ; then
16 | echo "Usage: $0 [-a] zipcode" >&2
17 | exit 1
18 | fi
19 |
20 | if [ $size -eq 5 ] ; then
21 | echo ""
22 |
23 | # get some information on the zipcode from the Census Bureau
24 |
25 | lynx -source "${llurl}$1" | \
26 | sed -n '/^/,/^Location:/p' | \
27 | sed 's/<[^>]*>//g;s/^ //g'
28 | fi
29 |
30 | # the weather forecast itself at accuweather.com
31 |
32 | lynx -source "${wxurl}$1" | \
33 | sed -n '/Start - Forecast Cell/,/End - Forecast Cell/p' | \
34 | sed 's/<[^>]*>//g;s/^ [ ]*//g' | \
35 | uniq | \
36 | head -$size
37 |
38 | exit 0
39 |
--------------------------------------------------------------------------------
/012-library-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Script to demonstrate use of the shell function library
4 |
5 | . 012-library.sh
6 |
7 | initializeANSI
8 |
9 | echon "First off, do you have echo in your path? (1=yes, 2=no) "
10 | read answer
11 | while ! validint $answer 1 2 ; do
12 | echon "${boldon}Try again${boldoff}. Do you have echo "
13 | echon "in your path? (1=yes, 2=no) "
14 | read answer
15 | done
16 |
17 | if ! checkForCmdInPath "echo" ; then
18 | echo "Nope, can't find the echo command."
19 | else
20 | echo "The echo command is in the PATH."
21 | fi
22 |
23 | echo ""
24 | echon "Enter a year you think might be a leap year: "
25 | read year
26 |
27 | while ! validint $year 1 9999 ; do
28 | echon "Please enter a year in the ${boldon}correct${boldoff} format: "
29 | read year
30 | done
31 |
32 | if isLeapYear $year ; then
33 | echo "${greenf}You're right! $year was a leap year.${reset}"
34 | else
35 | echo "${redf}Nope, that's not a leap year.${reset}"
36 | fi
37 |
38 | exit 0
39 |
--------------------------------------------------------------------------------
/077-checklinks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # checklinks - traverse all internal URLs on a Web site, reporting
4 | # any errors in the "traverse.errors" file.
5 |
6 | lynx="/usr/local/bin/lynx" # this might need to be tweaked
7 |
8 | # remove all the lynx traversal output files upon completion:
9 | trap "/bin/rm -f traverse*.errors reject*.dat traverse*.dat" 0
10 |
11 | if [ -z "$1" ] ; then
12 | echo "Usage: checklinks URL" >&2 ; exit 1
13 | fi
14 |
15 | $lynx -traversal "$1" > /dev/null
16 |
17 | if [ -s "traverse.errors" ] ; then
18 | echo -n $(wc -l < traverse.errors) errors encountered.
19 | echo \ Checked $(grep '^http' traverse.dat | wc -l) pages at ${1}:
20 | sed "s|$1||g" < traverse.errors
21 | else
22 | echo -n "No errors encountered. ";
23 | echo Checked $(grep '^http' traverse.dat | wc -l) pages at ${1}
24 | exit 0
25 | fi
26 |
27 | baseurl="$(echo $1 | cut -d/ -f3)"
28 | mv traverse.errors ${baseurl}.errors
29 | echo "(A copy of this output has been saved in ${baseurl}.errors)"
30 |
31 | exit 0
32 |
--------------------------------------------------------------------------------
/027-spelldict.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # spelldict - use the 'aspell' feature and some filtering to allow easy
4 | # command-line spell checking of a given input (file)
5 |
6 | okaywords="$HOME/.okaywords"
7 | tempout="/tmp/spell.tmp.$$"
8 | spell="virtual aspell" # tweak as needed
9 |
10 | trap "/bin/rm -f $tempout" EXIT
11 |
12 | if [ -z "$1" ] ; then
13 | echo "Usage: spell file|URL" >&2; exit 1
14 | elif [ ! -f $okaywords ] ; then
15 | echo "No personal dictionary found. Create one and rerun this command" >&2
16 | echo "Your dictionary file: $okaywords" >&2
17 | exit 1
18 | fi
19 |
20 | for filename
21 | do
22 | $spell -a < $filename | \
23 | grep -v '@(#)' | sed "s/\'//g" | \
24 | awk '{ if (length($0) > 15 && length($2) > 2) print $2 }' | \
25 | grep -vif $okaywords | \
26 | grep '[[:lower:]]' | grep -v '[[:digit:]]' | sort -u | \
27 | sed 's/^/ /' > $tempout
28 |
29 | if [ -s $tempout ] ; then
30 | sed "s/^/${filename}: /" $tempout
31 | fi
32 | done
33 |
34 | exit 0
35 |
--------------------------------------------------------------------------------
/051-enabled.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # enabled - show what services are enabled with inetd and xinetd,
4 | # if they're available on the system.
5 |
6 | iconf="/etc/inetd.conf"
7 | xconf="/etc/xinetd.conf"
8 | xdir="/etc/xinetd.d"
9 |
10 | if [ -r $iconf ] ; then
11 | echo "Services enabled in $iconf are:"
12 | grep -v '^#' $iconf | awk '{print " " $1}'
13 | echo ""
14 | if [ "$(ps -aux | grep inetd | egrep -vE '(xinet|grep)')" = "" ] ; then
15 | echo "** warning: inetd does not appear to be running"
16 | fi
17 | fi
18 |
19 | if [ -r $xconf ] ; then
20 | # don't need to look in xinietd.conf, just know it exists
21 | echo "Services enabled in $xdir are:"
22 |
23 | for service in $xdir/*
24 | do
25 | if ! $(grep disable $service | grep 'yes' > /dev/null) ; then
26 | echo -n " "
27 | basename $service
28 | fi
29 | done
30 |
31 | if ! $(ps -aux | grep xinetd | grep -v 'grep' > /dev/null) ; then
32 | echo "** warning: xinetd does not appear to be running"
33 | fi
34 | fi
35 |
36 | exit 0
37 |
--------------------------------------------------------------------------------
/061-getlinks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # getlinks - given a URL, return all of its internal and
4 | # external links
5 |
6 | if [ $# -eq 0 ] ; then
7 | echo "Usage: $0 [-d|-i|-x] url" >&2
8 | echo "-d=domains only, -i=internal refs only, -x=external only" >&2
9 | exit 1
10 | fi
11 |
12 | if [ $# -gt 1 ] ; then
13 | case "$1" in
14 | -d) lastcmd="cut -d/ -f3 | sort | uniq"
15 | shift
16 | ;;
17 | -i) basedomain="http://$(echo $2 | cut -d/ -f3)/"
18 | lastcmd="grep \"^$basedomain\" | sed \"s|$basedomain||g\" | sort | uniq"
19 | shift
20 | ;;
21 | -x) basedomain="http://$(echo $2 | cut -d/ -f3)/"
22 | lastcmd="grep -v \"^$basedomain\" | sort | uniq"
23 | shift
24 | ;;
25 | *) echo "$0: unknown option specified: $1" >&2; exit 1
26 | esac
27 | else
28 | lastcmd="sort | uniq"
29 | fi
30 |
31 | lynx -dump "$1" | \
32 | sed -n '/^References$/,$p' | \
33 | grep -E '[[:digit:]]+\.' | \
34 | awk '{print $2}' | \
35 | cut -d\? -f1 | \
36 | eval $lastcmd
37 |
38 | exit 0
39 |
--------------------------------------------------------------------------------
/071-getdope.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Within cron set it up so that every Friday, grab the latest column
4 | # of 'The Straight Dope' and mail it out to the specified recipient
5 |
6 | now="$(date +%y%m%d)"
7 | url="http://www.straightdope.com/columns/${now}.html"
8 | to="taylor"
9 |
10 | ( cat << EOF
11 | Subject: The Straight Dope for $(date "+%A, %d %B, %Y")
12 | From: Cecil Adams
13 | Content-type: text/html
14 | To: $to
15 |
16 |
17 |
18 |
21 | THE STRAIGHT DOPE
22 |
23 |
24 | EOF
25 |
26 | lynx -source "$url" | \
27 | sed -n '/
/,$p' | \
28 | sed 's|src="../art|src="http://www.straightdope.com/art|' |\
29 | sed 's|href="..|href="http://www.straightdope.com|g'
30 |
31 | echo ""
32 | ) | /usr/sbin/sendmail -t
33 |
34 | exit 0
35 |
--------------------------------------------------------------------------------
/085-enginehits.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # enginehits - extract and analyze search engine traffic in the
4 | # referrer field of a Common Log Format access log for a
5 | # specified domain name.
6 |
7 | maxmatches=25
8 | count=0
9 | temp="/tmp/$(basename $0).$$"
10 |
11 | trap "/bin/rm -f $temp" 0
12 |
13 | if [ $# -eq 0 -o ! -f "$1" ] ; then
14 | echo "Usage: $(basename $0) logfile searchdomain" >&2
15 | exit 1
16 | fi
17 |
18 | for URL in $(awk '{ if (length($11) > 4) { print $11 } }' "$1" | \
19 | grep $2)
20 | do
21 | args="$(echo $URL | cut -d\? -f2 | tr '&' '\n' | \
22 | grep -E '(^q=|^sid=|^p=|query=|item=|ask=|name=|topic=)' | \
23 | cut -d= -f2)"
24 | echo $args | sed -e 's/+/ /g' -e 's/"//g' >> $temp
25 | count="$(( $count + 1 ))"
26 | done
27 |
28 | echo "Search engine referrer info extracted $2 searches from ${1}:"
29 |
30 | sort $temp | uniq -c | sort -rn | head -$maxmatches | sed 's/^/ /g'
31 |
32 | echo ""
33 | echo Scanned $count $2 entries in log file out of $(wc -l < "$1") total.
34 |
35 | exit 0
36 |
--------------------------------------------------------------------------------
/050-set-date.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # setdate - friendly front-end to the date command
3 |
4 | # Date wants: [[[[[cc]yy]mm]dd]hh]mm[.ss]
5 |
6 | askvalue()
7 | {
8 | # $1 = field name, $2 = default value, $3 = max value,
9 | # $4 = required char/digit length
10 |
11 | echo -n "$1 [$2] : "
12 | read answer
13 | if [ ${answer:=$2} -gt $3 ] ; then
14 | echo "$0: $1 $answer is invalid"; exit 0
15 | elif [ "$(( $(echo $answer | wc -c) - 1 ))" -lt $4 ] ; then
16 | echo "$0: $1 $answer is too short: please specify $4 digits"; exit 0
17 | fi
18 | eval $1=$answer
19 | }
20 |
21 | eval $(date "+nyear=%Y nmon=%m nday=%d nhr=%H nmin=%M")
22 |
23 | askvalue year $nyear 3000 4
24 | askvalue month $nmon 12 2
25 | askvalue day $nday 31 2
26 | askvalue hour $nhr 24 2
27 | askvalue minute $nmin 59 2
28 |
29 | squished="$year$month$day$hour$minute"
30 | # or, if you're running a Linux system:
31 | # squished="$month$day$hour$minute$year"
32 |
33 | echo "Setting date to $squished. You might need to enter your sudo password:"
34 | sudo date $squished
35 |
36 | exit 0
37 |
--------------------------------------------------------------------------------
/073-photoalbum.cgi:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "Content-type: text/html"
4 | echo ""
5 |
6 | header="header.html"
7 | footer="footer.html"
8 | count=0
9 |
10 | if [ -f $header ] ; then
11 | cat $header
12 | else
13 | echo ""
14 | fi
15 |
16 | echo "Contents of $(dirname $SCRIPT_NAME)
"
17 | echo ""
18 |
19 | for name in *jpg
20 | do
21 | if [ $count -eq 4 ] ; then
22 | echo "| "
23 | count=1
24 | else
25 | echo " | "
26 | count=$(( $count + 1 ))
27 | fi
28 |
29 | nicename="$(echo $name | sed 's/.jpg//;s/-/ /g')"
30 |
31 | echo "![]() "
33 | echo "$nicename"
34 | done
35 |
36 | echo " |
"
37 |
38 | if [ -f $footer ] ; then
39 | cat $footer
40 | else
41 | echo ""
42 | fi
43 |
44 | exit 0
45 |
--------------------------------------------------------------------------------
/018-formatdir.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # formatdir - output a directory listing in a friendly and useful format
4 |
5 | gmk()
6 | {
7 | # given input in Kb, output in Kb, Mb or Gb for best output format
8 | if [ $1 -ge 1000000 ] ; then
9 | echo "$(scriptbc -p 2 $1 / 1000000)Gb"
10 | elif [ $1 -ge 1000 ] ; then
11 | echo "$(scriptbc -p 2 $1 / 1000)Mb"
12 | else
13 | echo "${1}Kb"
14 | fi
15 | }
16 |
17 | if [ $# -gt 1 ] ; then
18 | echo "Usage: $0 [dirname]" >&2; exit 1
19 | elif [ $# -eq 1 ] ; then
20 | cd "$@"
21 | fi
22 |
23 | for file in *
24 | do
25 | if [ -d "$file" ] ; then
26 | size=$(ls "$file" | wc -l | sed 's/[^[:digit:]]//g')
27 | if [ $size -eq 1 ] ; then
28 | echo "$file ($size entry)|"
29 | else
30 | echo "$file ($size entries)|"
31 | fi
32 | else
33 | size="$(ls -sk "$file" | awk '{print $1}')"
34 | echo "$file ($(gmk $size))|"
35 | fi
36 | done | \
37 | sed 's/ /^^^/g' | \
38 | xargs -n 2 | \
39 | sed 's/\^\^\^/ /g' | \
40 | awk -F\| '{ printf "%-39s %-39s\n", $1, $2 }'
41 |
42 | exit 0
43 |
--------------------------------------------------------------------------------
/029-loancalc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # mortgage - given a principal loan amount, interest rate, and
4 | # duration of loan (years), calculate the per-payment amount.
5 |
6 | # formula is: M = P * ( J / (1 - (1 + J) ** -N))
7 | # where P = principal, J = monthly interest rate, N = duration (months)
8 | #
9 | # users typically enter P, I (annual interest rate) and L (length, years)
10 |
11 | . 012-library.sh
12 |
13 | if [ $# -ne 3 ] ; then
14 | echo "Usage: $0 principal interest loan-duration-years" >&2
15 | exit 1
16 | fi
17 |
18 | P=$1 I=$2 L=$3
19 | J="$(scriptbc -p 8 $I / \( 12 \* 100 \) )"
20 | N="$(( $L * 12 ))"
21 | M="$(scriptbc -p 8 $P \* \( $J / \(1 - \(1 + $J\) \^ -$N\) \) )"
22 |
23 | # now a little prettying up of the value:
24 |
25 | dollars="$(echo $M | cut -d. -f1)"
26 | cents="$(echo $M | cut -d. -f2 | cut -c1-2)"
27 |
28 | cat << EOF
29 | A $L year loan at $I% interest with a principal amount of $(nicenumber $P 1 )
30 | results in a payment of \$$dollars.$cents each month for the duration of
31 | the loan ($N payments).
32 | EOF
33 |
34 | exit 0
35 |
--------------------------------------------------------------------------------
/049-findsuid.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # findsuid - find all SUID files or programs on the system other
4 | # than those that live in /bin and /usr/bin, and
5 | # output the matches in a friendly and useful format.
6 |
7 | mtime="7" # how far back (in days) to check for modified cmds
8 | verbose=0 # by default, let's be quiet about things
9 |
10 | if [ "$1" = "-v" ] ; then
11 | verbose=1
12 | fi
13 |
14 | for match in $(find /bin /usr/bin -type f -perm +4000 -print)
15 | do
16 | if [ -x $match ] ; then
17 |
18 | owner="$(ls -ld $match | awk '{print $3}')"
19 | perms="$(ls -ld $match | cut -c5-10 | grep 'w')"
20 |
21 | if [ ! -z $perms ] ; then
22 | echo "**** $match (writeable and setuid $owner)"
23 | elif [ ! -z $(find $match -mtime -$mtime -print) ] ; then
24 | echo "**** $match (modified within $mtime days and setuid $owner)"
25 | elif [ $verbose -eq 1 ] ; then
26 | lastmod="$(ls -ld $match | awk '{print $6, $7, $8}')"
27 | echo " $match (setuid $owner, last modified $lastmod)"
28 | fi
29 | fi
30 | done
31 |
32 | exit 0
33 |
34 |
--------------------------------------------------------------------------------
/095-addmacalias.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # addalias - add a new alias to the email alias database on Mac OS X
4 | # this presumes that you've enabled sendmail, which can be kind of
5 | # tricky. Go to http://www.macdevcenter.com/ and search for 'sendmail'
6 | # for some good reference works.
7 |
8 | showaliases="nidump aliases ."
9 |
10 | if [ "$(/usr/bin/whoami)" != "root" ] ; then
11 | echo "$(basename $0): You must be root to run this command." >&2
12 | exit 1
13 | fi
14 |
15 | if [ $# -eq 0 ] ; then
16 | echo -n "Alias to create: "
17 | read alias
18 | else
19 | alias=$1
20 | fi
21 |
22 | # now let's check to see if that alias already exists...
23 |
24 | if $showaliases | grep "${alias}:" >/dev/null 2>&1 ; then
25 | echo "$0: mail alias $alias already exists" >&2
26 | exit 1
27 | fi
28 |
29 | # looks good. let's get the RHS and inject it into NetInfo
30 |
31 | echo -n "pointing to: "
32 | read rhs
33 |
34 | niutil -create . /aliases/$alias
35 | niutil -createprop . /aliases/$alias name $alias
36 | niutil -createprop . /aliases/$alias members "$rhs"
37 |
38 | echo "Alias $alias created without incident."
39 |
40 | exit 0
41 |
--------------------------------------------------------------------------------
/071-kevin-and-kell.cgi:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # kevin-and-kell.cgi - Build a Web page on-the-fly to display the latest
4 | # strip from the cartoon strip Kevin and Kell, by Bill Holbrook
5 | #
6 |
7 | month="$(date +%m)"
8 | day="$(date +%d)"
9 | year="$(date +%y)"
10 |
11 | echo "Content-type: text/html"
12 | echo ""
13 |
14 | echo ""
15 | echo "Kevin & Kell"
16 | echo ""
17 | echo ""
18 | echo "| Bill Holbrook's Kevin & Kell |
"
19 | echo " "
25 |
26 | echo " |
| "
27 | echo "© Bill Holbrook. Please see "
28 | echo "kevinandkell.com"
29 | echo "for more strips, books, etc."
30 | echo " |
"
31 |
32 | exit 0
33 |
--------------------------------------------------------------------------------
/024-calc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # calc - a command-line calculator that acts as a front-end to bc
4 |
5 | scale=2
6 |
7 | show_help()
8 | {
9 | cat << EOF
10 | In addition to standard math functions, calc also supports
11 |
12 | a % b remainder of a/b
13 | a ^ b exponential: a raised to the b power
14 | s(x) sine of x, x in radians
15 | c(x) cosine of x, x in radians
16 | a(x) arctangent of x, returns radians
17 | l(x) natural log of x
18 | e(x) exponential log of raising e to the x
19 | j(n,x) bessel function of integer order n of x
20 | scale N show N fractional digits (default = 2)
21 | EOF
22 | }
23 |
24 | if [ $# -gt 0 ] ; then
25 | exec scriptbc "$@"
26 | fi
27 |
28 | echo "Calc - a simple calculator. Use 'help' for help, 'quit' to quit."
29 |
30 | echo -n "calc> "
31 |
32 | while read command args
33 | do
34 | case $command
35 | in
36 | quit|exit) exit 0 ;;
37 | help|\?) show_help ;;
38 | scale) scale=$args ;;
39 | *) scriptbc -p $scale "$command" "$args" ;;
40 | esac
41 |
42 | echo -n "calc> "
43 | done
44 |
45 | echo ""
46 |
47 | exit 0
48 |
--------------------------------------------------------------------------------
/090-getstats.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # getstats - every 'n' minutes, grab netstats values (via crontab)
4 |
5 | logfile="/var/log/netstat.log"
6 | temp="/tmp/getstats.tmp"
7 |
8 | trap "/bin/rm -f $temp" 0
9 |
10 | ( echo -n "time=$(date +%s);"
11 |
12 | netstat -s -p tcp > $temp
13 |
14 | sent="$(grep 'packets sent' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
15 | resent="$(grep 'retransmitted' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
16 | received="$(grep 'packets received$' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
17 | dupacks="$(grep 'duplicate acks' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
18 | outoforder="$(grep 'out-of-order packets' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
19 | connectreq="$(grep 'connection requests' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
20 | connectacc="$(grep 'connection accepts' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
21 | retmout="$(grep 'retransmit timeouts' $temp | cut -d\ -f1 | sed 's/[^[:digit:]]//g')"
22 |
23 | echo -n "snt=$sent;re=$resent;rec=$received;dup=$dupacks;"
24 | echo -n "oo=$outoforder;creq=$connectreq;cacc=$connectacc;"
25 | echo "reto=$retmout"
26 |
27 | ) >> $logfile
28 |
29 | exit 0
30 |
--------------------------------------------------------------------------------
/state.capitals.txt:
--------------------------------------------------------------------------------
1 | Alabama Montgomery
2 | Alaska Juneau
3 | Arizona Phoenix
4 | Arkansas Little-Rock
5 | California Sacramento
6 | Colorado Denver
7 | Connecticut Hartford
8 | Delaware Dover
9 | Florida Tallahassee
10 | Georgia Atlanta
11 | Hawaii Honolulu
12 | Idaho Boise
13 | Illinois Springfield
14 | Indiana Indianapolis
15 | Iowa Des-Moines
16 | Kansas Topeka
17 | Kentucky Frankfort
18 | Louisiana Baton-Rouge
19 | Maine Augusta
20 | Maryland Annapolis
21 | Massachusetts Boston
22 | Michigan Lansing
23 | Minnesota St.-Paul
24 | Mississippi Jackson
25 | Missouri Jefferson-City
26 | Montana Helena
27 | Nebraska Lincoln
28 | Nevada Carson-City
29 | New-Hampshire Concord
30 | New-Jersey Trenton
31 | New-Mexico Santa-Fe
32 | New-York Albany
33 | North-Carolina Raleigh
34 | North-Dakota Bismarck
35 | Ohio Columbus
36 | Oklahoma Oklahoma-City
37 | Oregon Salem Portland
38 | Pennsylvania Harrisburg
39 | Rhode-Island Providence
40 | South-Carolina Columbia
41 | South-Dakota Pierre
42 | Tennessee Nashville
43 | Texas Austin
44 | Utah Salt-Lake-City
45 | Vermont Montpelier
46 | Virginia Richmond
47 | Washington Olympia
48 | West-Virginia Charleston
49 | Wisconsin Madison
50 | Wyoming Cheyenne
51 |
--------------------------------------------------------------------------------
/093-listmacusers.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Simple script to list users in the Mac OS X NetInfo database
4 | # note that Mac OS X also has an /etc/passwd file, but that's
5 | # only used during the initial stages of boot time and for
6 | # recovery bootups. Otherwise, all data is in the NetInfo db.
7 |
8 | fields=""
9 |
10 | while getopts "Aahnprsu" opt ; do
11 | case $opt in
12 | A ) fields="uid passwd name realname home shell" ;;
13 | a ) fields="uid name realname home shell" ;;
14 | h ) fields="$fields home" ;;
15 | n ) fields="$fields name" ;;
16 | p ) fields="$fields passwd" ;;
17 | r ) fields="$fields realname" ;;
18 | s ) fields="$fields shell" ;;
19 | u ) fields="$fields uid" ;;
20 | ? ) cat << EOF >&2
21 | Usage: $0 [A|a|hnprsu]
22 | Where:
23 | -A output all known NetInfo user fields
24 | -a output only the interesting user fields
25 | -h show home directories of accounts
26 | -n show account names
27 | -p passwd (encrypted)
28 | -r show realname/fullname values
29 | -s show login shell
30 | -u uid
31 | EOF
32 | exit 1
33 | esac
34 | done
35 |
36 | exec nireport . /users ${fields:=uid name realname home shell}
37 |
--------------------------------------------------------------------------------
/030-agenda.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # agenda - scan through the user's .agenda file to see if there
4 | # are any matches for the current or next day
5 |
6 | agendafile="$HOME/.agenda"
7 |
8 | checkDate()
9 | {
10 | # create the possible default values that'll match today
11 | weekday=$1 day=$2 month=$3 year=$4
12 | format1="$weekday" format2="$day$month" format3="$day$month$year"
13 |
14 | # and step through the file comparing dates...
15 |
16 | IFS="|" # The reads will naturally split at the IFS
17 |
18 | echo "On the Agenda for today:"
19 |
20 | while read date description ; do
21 | if [ "$date" = "$format1" -o "$date" = "$format2" -o "$date" = "$format3" ]
22 | then
23 | echo " $description"
24 | fi
25 | done < $agendafile
26 | }
27 |
28 | if [ ! -e $agendafile ] ; then
29 | echo "$0: You don't seem to have an .agenda file. " >&2
30 | echo "To remedy this, please use 'addagenda' to add events" >&2
31 | exit 1
32 | fi
33 |
34 | # now let's get today's date...
35 |
36 | eval $(date "+weekday=\"%a\" month=\"%b\" day=\"%e\" year=\"%G\"")
37 |
38 | day="$(echo $day|sed 's/ //g')" # remove possible leading space
39 |
40 | checkDate $weekday $day $month $year
41 |
42 | exit 0
43 |
--------------------------------------------------------------------------------
/083-ssync.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # ssync - If anything's changed, Create a tarball and sync a remote
4 | # directory via sftp using sftpsync.
5 |
6 | sftpacct="taylor@intuitive.com"
7 | tarballname="AllFiles.tgz"
8 | localsource="$HOME/scripts"
9 | remotedir="shellhacks/scripts"
10 | timestamp=".timestamp"
11 |
12 | sftpsync="$HOME/scripts/sftpsync"
13 |
14 | # first off, let's see if the local dir exists and has files.
15 |
16 | if [ ! -d $localsource ] ; then
17 | echo "$0: Error: directory $localsource doesn't exist?" >&2
18 | exit 1
19 | fi
20 |
21 | cd $localsource
22 |
23 | # now let's count files to ensure something's changed:
24 |
25 | if [ ! -f $timestamp ] ; then
26 | for filename in *
27 | do
28 | if [ -f "$filename" ] ; then
29 | count=$(( $count + 1 ))
30 | fi
31 | done
32 | else
33 | count=$(find . -newer $timestamp -type f -print | wc -l)
34 | fi
35 |
36 | if [ ${count:-0} -eq 0 ] ; then
37 | echo "$0: No files found in $localsource to sync with remote." >&2
38 | exit 0
39 | fi
40 |
41 | echo "Making tarball archive file for upload"
42 |
43 | tar -czf $tarballname ./*
44 |
45 | # Done! Now let's switch to the sftpsync script
46 |
47 | exec $sftpsync $sftpacct $remotedir
48 |
49 |
--------------------------------------------------------------------------------
/021-findman.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # findman -- given a pattern and a man section, show all the matches
4 | # for that pattern from within all relevant man pages.
5 |
6 | match1="/tmp/$0.1.$$"
7 | matches="/tmp/$0.$$"
8 | manpagelist=""
9 |
10 | trap "rm -f $match1 $matches" EXIT
11 |
12 | case $#
13 | in
14 | 3 ) section="$1" cmdpat="$2" manpagepat="$3" ;;
15 | 2 ) section="" cmdpat="$1" manpagepat="$2" ;;
16 | * ) echo "Usage: $0 [section] cmdpattern manpagepattern" >&2
17 | exit 1
18 | esac
19 |
20 | if ! man -k "$cmdpat" | grep "($section" > $match1 ; then
21 | echo "No matches to pattern \"$cmdpat\". Try something broader?"; exit 1
22 | fi
23 |
24 | cut -d\( -f1 < $match1 > $matches # command names only
25 | cat /dev/null > $match1 # clear the file...
26 |
27 | for manpage in $(cat $matches)
28 | do
29 | manpagelist="$manpagelist $manpage"
30 | man $manpage | col -b | grep -i $manpagepat | \
31 | sed "s/^/${manpage}: /" | tee -a $match1
32 | done
33 |
34 | if [ ! -s $match1 ] ; then
35 | cat << EOF
36 | Command pattern "$cmdpat" had matches, but within those there were no
37 | matches to your man page pattern "$manpagepat" found in that set.
38 | Man pages checked:$manpagelist
39 | EOF
40 | fi
41 |
42 | exit 0
43 |
--------------------------------------------------------------------------------
/066-getexchrate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # getexchrate - scrape the current currency exchange rates
4 | # from CNN's money and finance Web site.
5 | #
6 | # Without any flags, this grabs the exchange rate values if the
7 | # current information is more than 12 hours old. It also shows
8 | # success upon completion: something to take into account if
9 | # you run this from a cron job.
10 |
11 | url="http://money.cnn.com/markets/currencies/crosscurr.html"
12 | age="+720" # 12 hours, in minutes
13 | outf="/tmp/.exchangerate"
14 |
15 | # Do we need the new exchange rate values? Let's check to see:
16 | # if the file is less than 12 hours old, the find fails ...
17 |
18 | if [ -f $outf ] ; then
19 | if [ -z "$(find $outf -cmin $age -print)" ]; then
20 | echo "$0: exchange rate data is up-to-date." >&2
21 | exit 1
22 | fi
23 | fi
24 |
25 | # Actually get the latest exchange rates, translating into the
26 | # format required by the exchrate script.
27 |
28 | lynx -dump 'http://money.cnn.com/markets/currencies/crosscurr.html' | \
29 | grep -E '(Japan|Euro|Can|UK)' | \
30 | awk '{ if (NF == 5 ) { print $1"="$2} }' | \
31 | tr '[:upper:]' '[:lower:]' | \
32 | sed 's/dollar/cand/' > $outf
33 |
34 | echo "Success. Exchange rates updated at $(date)."
35 |
36 | exit 0
37 |
--------------------------------------------------------------------------------
/010-filelock.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # filelock - a flexible file locking mechanism
4 |
5 | retries="10" # default number of retries: 10
6 | action="lock" # default action
7 | nullcmd="/bin/true" # null command for lockf
8 |
9 | while getopts "lur:" opt; do
10 | case $opt in
11 | l ) action="lock" ;;
12 | u ) action="unlock" ;;
13 | r ) retries="$OPTARG" ;;
14 | esac
15 | done
16 | shift $(($OPTIND - 1))
17 |
18 | if [ $# -eq 0 ] ; then
19 | cat << EOF >&2
20 | Usage: $0 [-l|-u] [-r retries] lockfilename
21 | Where -l requests a lock (the default), -u requests an unlock, -r X
22 | specifies a maximum number of retries before it fails (default = $retries).
23 | EOF
24 | exit 1
25 | fi
26 |
27 | # ascertain whether we have lockf or lockfile system apps
28 |
29 | if [ -z "$(which lockfile | grep -v '^no ')" ] ; then
30 | echo "$0 failed: 'lockfile' utility not found in PATH." >&2
31 | exit 1
32 | fi
33 |
34 | if [ "$action" = "lock" ] ; then
35 | if ! lockfile -1 -r $retries "$1" 2> /dev/null; then
36 | echo "$0: Failed: Couldn't create lockfile in time" >&2
37 | exit 1
38 | fi
39 | else # action = unlock
40 | if [ ! -f "$1" ] ; then
41 | echo "$0: Warning: lockfile $1 doesn't exist to unlock" >&2
42 | exit 1
43 | fi
44 | rm -f "$1"
45 | fi
46 |
47 | exit 0
48 |
--------------------------------------------------------------------------------
/043-slocate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # slocate - Try to search the user's secure locate database for the
4 | # specified pattern. If none exists, output a warning and create
5 | # one. If secure locate db is empty, use system one instead.
6 |
7 | locatedb="/var/locate.db"
8 | slocatedb="$HOME/.slocatedb"
9 |
10 | if [ "$1" = "--explain" ] ; then
11 | cat << "EOF" >&2
12 | Warning: Secure locate keeps a private database for each user, and your
13 | database hasn't yet been created. Until it is (probably late tonight)
14 | I'll just use the public locate database, which will show you all
15 | publicly accessible matches, rather than those explicitly available to
16 | account ${USER:-$LOGNAME}.
17 | EOF
18 | if [ "$1" = "--explain" ] ; then
19 | exit 0
20 | fi
21 |
22 | # before we go, create a .slocatedb so that cron will fill it
23 | # the next time the mkslocatedb script is run
24 |
25 | touch $slocatedb # mkslocatedb will build it next time through
26 | chmod 600 $slocatedb # start on the right foot with permissions
27 |
28 | elif [ -s $slocatedb ] ; then
29 | locatedb=$slocatedb
30 | else
31 | echo "Warning: using public database. Use \"$0 --explain\" for details." >&2
32 | fi
33 |
34 | if [ -z "$1" ] ; then
35 | echo "Usage: $0 pattern" >&2; exit 1
36 | fi
37 |
38 | exec grep -i "$1" $locatedb
39 |
--------------------------------------------------------------------------------
/020-DIR.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # DIR - pretend we're the DIR command in DOS and display the contents
3 | # of the specified file, accepting some of the standard DIR flags
4 |
5 | usage()
6 | {
7 | cat << EOF >&2
8 | Usage: $0 [DOS flags] directory or directories
9 | Where:
10 | /D sort by columns
11 | /H show help for this shell script
12 | /N show long listing format with filenames on right
13 | /OD sort by oldest to newest
14 | /O-D sort by newest to oldest
15 | /P pause after each screenful of information
16 | /Q show owner of the file
17 | /S recursive listing
18 | /W use wide listing format
19 | EOF
20 | exit 0
21 | }
22 |
23 | postcmd=""
24 | flags=""
25 |
26 | while [ $# -gt 0 ]
27 | do
28 | case $1 in
29 | /D ) flags="$flags -x" ;;
30 | /H ) usage ;;
31 | /[NQW] ) flags="$flags -l" ;;
32 | /OD ) flags="$flags -rt" ;;
33 | /O-D ) flags="$flags -t" ;;
34 | /P ) postcmd="more" ;;
35 | /S ) flags="$flags -s" ;;
36 | * ) # unknown flag: probably a dir specifier
37 | break; # so let's get outta the while loop
38 | esac
39 | shift # processed flag, let's see if there's another
40 | done
41 |
42 | # done processing flags, now the command itself:
43 |
44 | if [ ! -z "$postcmd" ] ; then
45 | ls $flags "$@" | $postcmd
46 | else
47 | ls $flags "$@"
48 | fi
49 |
50 | exit 0
51 |
--------------------------------------------------------------------------------
/057-archivedir.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # archivedir - create a compressed archive of the specified directory
4 |
5 | maxarchivedir=10 # size, in blocks, of 'big' directory, to confirm
6 | compress=gzip # change to your favorite compress app
7 | progname=$(basename $0)
8 |
9 | if [ $# -eq 0 ] ; then
10 | echo "Usage: $progname directory" >&2 ;exit 1
11 | fi
12 |
13 | if [ ! -d $1 ] ; then
14 | echo "${progname}: can't find directory $1 to archive." >&2; exit 1
15 | fi
16 |
17 | if [ "$(basename $1)" != "$1" -o "$1" = "." ] ; then
18 | echo "${progname}: You must specify a subdirectory" >&2
19 | exit 1
20 | fi
21 |
22 | if [ ! -w . ] ; then
23 | echo "${progname}: cannot write archive file to current directory." >&2
24 | exit 1
25 | fi
26 |
27 | dirsize="$(du -s $1 | awk '{print $1}')"
28 |
29 | if [ $dirsize -gt $maxarchivedir ] ; then
30 | echo -n "Warning: directory $1 is $dirsize blocks. Proceed? [n] "
31 | read answer
32 | answer="$(echo $answer | tr '[:upper:]' '[:lower:]' | cut -c1)"
33 | if [ "$answer" != "y" ] ; then
34 | echo "${progname}: archive of directory $1 cancelled." >&2
35 | exit 0
36 | fi
37 | fi
38 |
39 | archivename="$(echo $1 | sed 's/$/.tgz/')"
40 |
41 | if tar cf - $1 | $compress > $archivename ; then
42 | echo "Directory $1 archived as $archivename"
43 | else
44 | echo "Warning: tar encountered errors archiving $1"
45 | fi
46 |
47 | exit 0
48 |
--------------------------------------------------------------------------------
/079-webspell.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # webspell - use the 'aspell' feature + lynx to spell check either a
4 | # Web page URL or a file.
5 |
6 | # Inevitably you'll find that there are words it flags as wrong, but
7 | # you think are fine. Simply save them in a file, one-per-line, and
8 | # ensure that 'okaywords' points to that file.
9 |
10 | okaywords="$HOME/.okaywords"
11 | tempout="/tmp/webspell.$$"
12 | trap "/bin/rm -f $tempout" 0
13 |
14 | if [ $# -eq 0 ] ; then
15 | echo "Usage: webspell file|URL" >&2; exit 1
16 | fi
17 |
18 | for filename
19 | do
20 | if [ ! -f "$filename" -a "$(echo $filename|cut -c1-7)" != "http://" ] ; then
21 | continue; # picked up directory in '*' listing
22 | fi
23 |
24 | lynx -dump $filename | tr ' ' '\n' | sort -u | \
25 | grep -vE "(^[^a-z]|')" | \
26 | # adjust the following line to produce just a list of misspelled words
27 | ispell -a | awk '/^\&/ { print $2 }' | \
28 | sort -u > $tempout
29 |
30 | if [ -r $okaywords ] ; then
31 | # if you have an okaywords file, screen okay words out
32 | grep -vif $okaywords < $tempout > ${tempout}.2
33 | mv ${tempout}.2 $tempout
34 | fi
35 |
36 | if [ -s $tempout ] ; then
37 | echo "Probable spelling errors: ${filename}"
38 | echo '-------' ; cat $tempout ; echo '========='
39 | cat $tempout | paste - - - - | sed 's/^/ /'
40 | fi
41 | done
42 |
43 | exit 0
44 |
--------------------------------------------------------------------------------
/040-diskhogs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # DISKHOGS - Disk quota analysis tool for Unix, assumes all user
4 | # accounts are >= UID 100. Emails message to each violating user
5 | # and reports a summary to the screen
6 |
7 | MAXDISKUSAGE=20
8 | violators="/tmp/diskhogs0.$$"
9 |
10 | trap "/bin/rm -f $violators" 0
11 |
12 | for name in $(cut -d: -f1,3 /etc/passwd | awk -F: '$2 > 99 { print $1 }')
13 | do
14 | echo -n "$name "
15 |
16 | find / /usr /var /Users -user $name -xdev -type f -ls | \
17 | awk '{ sum += $7 } END { print sum / (1024*1024) }'
18 |
19 | done | awk "\$2 > $MAXDISKUSAGE { print \$0 }" > $violators
20 |
21 | if [ ! -s $violators ] ; then
22 | echo "No users exceed the disk quota of ${MAXDISKUSAGE}MB"
23 | cat $violators
24 | exit 0
25 | fi
26 |
27 | while read account usage ; do
28 |
29 | cat << EOF | fmt | mail -s "Warning: $account Exceeds Quota" $account
30 | Your disk usage is ${usage}MB but you have only been allocated
31 | ${MAXDISKUSAGE}MB. This means that either you need to delete some of
32 | your files, compress your files (see 'gzip' or 'bzip2' for powerful and
33 | easy-to-use compression programs), or talk with us about increasing
34 | your disk allocation.
35 |
36 | Thanks for your cooperation on this matter.
37 |
38 | Dave Taylor @ x554
39 | EOF
40 |
41 | echo "Account $account has $usage MB of disk space. User notified."
42 |
43 | done < $violators
44 |
45 | exit 0
46 |
--------------------------------------------------------------------------------
/075-counter.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # counter - a simple text-based page counter, with appropriate locking
4 |
5 | myhome="/home/taylor/web/wicked/examples"
6 | counter="$myhome/counter.dat"
7 | lockfile="$myhome/counter.lck"
8 | updatecounter="$myhome/updatecounter"
9 |
10 | # Note that this script is not intended to be called directly from
11 | # a web browser so it doesn't use the otherwise obligatory
12 | # content-type header material.
13 |
14 | # ascertain whether we have lockf or lockfile system apps
15 |
16 | if [ -z $(which lockf) ] ; then
17 | if [ -z $(which lockfile) ] ; then
18 | echo "(counter: no locking utility available)
"
19 | exit 0
20 | else # proceed with the lockfile command
21 | if [ ! -f $counter ] ; then
22 | echo "0" # it'll be created shortly
23 | else
24 | cat $counter
25 | fi
26 |
27 | trap "/bin/rm -f $lockfile" 0
28 |
29 | lockfile -1 -l 10 -s 2 $lockfile
30 | if [ $? -ne 0 ] ; then
31 | echo "(counter: couldn't create lockfile in time)"
32 | exit 0
33 | fi
34 | $updatecounter $counter
35 | fi
36 | else
37 | if [ ! -f $counter ] ; then
38 | echo "0" # it'll be created shortly
39 | else
40 | cat $counter
41 | fi
42 |
43 | lockf -s -t 10 $lockfile $updatecounter $counter
44 | if [ $? -ne 0 ] ; then
45 | echo "(counter: couldn't create lockfile in time)"
46 | fi
47 | fi
48 |
49 | exit 0
50 |
--------------------------------------------------------------------------------
/044-adduser.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # ADDUSER - add a new user to the system, including building their
4 | # home directory, copying in default config data, etc.
5 | # For a standard Unix/Linux system, not Mac OS X
6 |
7 | pwfile="/etc/passwd" shadowfile="/etc/shadow"
8 | gfile="/etc/group"
9 | hdir="/home"
10 |
11 | if [ "$(whoami)" != "root" ] ; then
12 | echo "Error: You must be root to run this command." >&2
13 | exit 1
14 | fi
15 |
16 | echo "Add new user account to $(hostname)"
17 | echo -n "login: " ; read login
18 |
19 | # adjust '5000' to match the top end of your user account namespace
20 | # because some system accounts have uid's like 65535 and similar.
21 |
22 | uid="$(awk -F: '{ if (big < $3 && $3 < 5000) big=$3 } END { print big + 1 }' $pwfile)"
23 | homedir=$hdir/$login
24 |
25 | # we are giving each user their own group, so gid=uid
26 | gid=$uid
27 |
28 | echo -n "full name: " ; read fullname
29 | echo -n "shell: " ; read shell
30 |
31 | echo "Setting up account $login for $fullname..."
32 |
33 | echo ${login}:x:${uid}:${gid}:${fullname}:${homedir}:$shell >> $pwfile
34 | echo ${login}:*:11647:0:99999:7::: >> $shadowfile
35 |
36 | echo "${login}:x:${gid}:$login" >> $gfile
37 |
38 | mkdir $homedir
39 | cp -R /etc/skel/.[a-zA-Z]* $homedir
40 | chmod 755 $homedir
41 | find $homedir -print | xargs chown ${login}:$login
42 |
43 | # setting an initial password
44 | passwd $login
45 |
46 | exit 0
47 |
--------------------------------------------------------------------------------
/085-searchinfo.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # searchinfo - extract and analyze search engine traffic indicated in the
4 | # referrer field of a Common Log Format access log.
5 |
6 | host="intuitive.com" # change to your domain, as desired
7 | maxmatches=20
8 | count=0
9 | temp="/tmp/$(basename $0).$$"
10 |
11 | trap "/bin/rm -f $temp" 0
12 |
13 | if [ $# -eq 0 ] ; then
14 | echo "Usage: $(basename $0) logfile" >&2
15 | exit 1
16 | fi
17 | if [ ! -r "$1" ] ; then
18 | echo "Error: can't open file $1 for analysis." >&2
19 | exit 1
20 | fi
21 |
22 | for URL in $(awk '{ if (length($11) > 4) { print $11 } }' "$1" | \
23 | grep -vE "(/www.$host|/$host)" | grep '?')
24 | do
25 | searchengine="$(echo $URL | cut -d/ -f3 | rev | cut -d. -f1-2 | rev)"
26 | args="$(echo $URL | cut -d\? -f2 | tr '&' '\n' | \
27 | grep -E '(^q=|^sid=|^p=|query=|item=|ask=|name=|topic=)' | \
28 | sed -e 's/+/ /g' -e 's/%20/ /g' -e 's/"//g' | cut -d= -f2)"
29 |
30 | if [ ! -z "$args" ] ; then
31 | echo "${searchengine}: $args" >> $temp
32 | else
33 | # no well-known match, show entire GET string instead...
34 | echo "${searchengine} $(echo $URL | cut -d\? -f2)" >> $temp
35 | fi
36 | count="$(( $count + 1 ))"
37 | done
38 |
39 | echo "Search engine referrer info extracted from ${1}:"
40 |
41 | sort $temp | uniq -c | sort -rn | head -$maxmatches | sed 's/^/ /g'
42 |
43 | echo ""
44 | echo Scanned $count entries in log file out of $(wc -l < "$1") total.
45 |
46 | exit 0
47 |
--------------------------------------------------------------------------------
/011-colors.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # ANSI Color -- use these variables to easily have different color
4 | # and format output. Make sure to output the reset sequence after
5 | # colors (f = foreground, b = background), and use the 'off'
6 | # feature for anything you turn on.
7 |
8 | initializeANSI()
9 | {
10 | esc=""
11 |
12 | blackf="${esc}[30m"; redf="${esc}[31m"; greenf="${esc}[32m"
13 | yellowf="${esc}[33m" bluef="${esc}[34m"; purplef="${esc}[35m"
14 | cyanf="${esc}[36m"; whitef="${esc}[37m"
15 |
16 | blackb="${esc}[40m"; redb="${esc}[41m"; greenb="${esc}[42m"
17 | yellowb="${esc}[43m" blueb="${esc}[44m"; purpleb="${esc}[45m"
18 | cyanb="${esc}[46m"; whiteb="${esc}[47m"
19 |
20 | boldon="${esc}[1m"; boldoff="${esc}[22m"
21 | italicson="${esc}[3m"; italicsoff="${esc}[23m"
22 | ulon="${esc}[4m"; uloff="${esc}[24m"
23 | invon="${esc}[7m"; invoff="${esc}[27m"
24 |
25 | reset="${esc}[0m"
26 | }
27 |
28 | # note in this first use that switching colors doesn't require a reset
29 | # first - the new color overrides the old one.
30 |
31 | initializeANSI
32 |
33 | cat << EOF
34 | ${yellowf}This is a phrase in yellow${redb} and red${reset}
35 | ${boldon}This is bold${ulon} this is italics${reset} bye bye
36 | ${italicson}This is italics${italicsoff} and this is not
37 | ${ulon}This is ul${uloff} and this is not
38 | ${invon}This is inv${invoff} and this is not
39 | ${yellowf}${redb}Warning I${yellowb}${redf}Warning II${reset}
40 | EOF
41 |
--------------------------------------------------------------------------------
/065-moviedata.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # moviedata - given a movie title, return a list of matches, if
4 | # there's more than one, or a synopsis of the movie if there's
5 | # just one. Uses the Internet Movie Database (imdb.com)
6 |
7 | imdburl="http://us.imdb.com/Tsearch?restrict=Movies+only&title="
8 | titleurl="http://us.imdb.com/Title?"
9 | tempout="/tmp/moviedata.$$"
10 |
11 | summarize_film()
12 | {
13 | # produce an attractive synopsis of the film
14 |
15 | grep "^" $tempout | sed 's/<[^>]*>//g;s/(more)//'
16 | grep 'Plot Outline:' $tempout | \
17 | sed 's/<[^>]*>//g;s/(more)//;s/(view trailer)//' |fmt|sed 's/^/ /'
18 | exit 0
19 | }
20 |
21 | trap "rm -f $tempout" 0 1 15
22 |
23 | if [ $# -eq 0 ] ; then
24 | echo "Usage: $0 {movie title | movie ID}" >&2
25 | exit 1
26 | fi
27 |
28 | fixedname="$(echo $@ | tr ' ' '+')" # for the URL
29 |
30 | if [ $# -eq 1 ] ; then
31 | nodigits="$(echo $1 | sed 's/[[:digit:]]*//g')"
32 | if [ -z "$nodigits" ] ; then
33 | lynx -source "$titleurl$fixedname" > $tempout
34 | summarize_film
35 | fi
36 | fi
37 |
38 | url="$imdburl$fixedname"
39 |
40 | lynx -source $url > $tempout
41 |
42 | if [ ! -z "$(grep "IMDb title search" $tempout)" ] ; then
43 | grep 'HREF="/Title?' $tempout | \
44 | sed 's/- / -- /;s/<.*//;s/\/Title?//' | \
46 | sort -u | \
47 | more
48 | else
49 | summarize_film
50 | fi
51 |
52 | exit 0
53 |
--------------------------------------------------------------------------------
/083-sftpsync.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # sftpsync - Given a target directory on an sftp server, make sure that
4 | # all new or modified files are uploaded to the remote system. Uses
5 | # a timestamp file ingeniously called .timestamp to keep track.
6 |
7 | timestamp=".timestamp"
8 | tempfile="/tmp/sftpsync.$$"
9 | count=0
10 |
11 | trap "/bin/rm -f $tempfile" 0 1 15 # zap tempfile on exit &sigs
12 |
13 | if [ $# -eq 0 ] ; then
14 | echo "Usage: $0 user@host { remotedir }" >&2
15 | exit 1
16 | fi
17 |
18 | user="$(echo $1 | cut -d@ -f1)"
19 | server="$(echo $1 | cut -d@ -f2)"
20 |
21 | if [ $# -gt 1 ] ; then
22 | echo "cd $2" >> $tempfile
23 | fi
24 |
25 | if [ ! -f $timestamp ] ; then
26 | # no timestamp file, upload all files
27 | for filename in *
28 | do
29 | if [ -f "$filename" ] ; then
30 | echo "put -P \"$filename\"" >> $tempfile
31 | count=$(( $count + 1 ))
32 | fi
33 | done
34 | else
35 | for filename in $(find . -newer $timestamp -type f -print)
36 | do
37 | echo "put -P \"$filename\"" >> $tempfile
38 | count=$(( $count + 1 ))
39 | done
40 | fi
41 |
42 | if [ $count -eq 0 ] ; then
43 | echo "$0: No files require uploading to $server" >&2
44 | exit 1
45 | fi
46 |
47 | echo "quit" >> $tempfile
48 |
49 | echo "Synchronizing: Found $count files in local folder to upload."
50 |
51 | if ! sftp -b $tempfile "$user@$server" ; then
52 | echo "Done. All files synchronized up with $server"
53 | touch $timestamp
54 | fi
55 |
56 | exit 0
57 |
--------------------------------------------------------------------------------
/003-normdate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # normdate - Normalizes month field in date specification
3 | # to three letters, first letter capitalized. A helper
4 | # function for hack #7, validdate. Exits w/ zero if no error.
5 |
6 | monthnoToName()
7 | {
8 | # sets the variable 'month' to the appropriate value
9 | case $1 in
10 | 1 ) month="Jan" ;; 2 ) month="Feb" ;;
11 | 3 ) month="Mar" ;; 4 ) month="Apr" ;;
12 | 5 ) month="May" ;; 6 ) month="Jun" ;;
13 | 7 ) month="Jul" ;; 8 ) month="Aug" ;;
14 | 9 ) month="Sep" ;; 10) month="Oct" ;;
15 | 11) month="Nov" ;; 12) month="Dec" ;;
16 | * ) echo "$0: Unknown numeric month value $1" >&2; exit 1
17 | esac
18 | return 0
19 | }
20 |
21 | ## Begin main script
22 |
23 | if [ $# -eq 1 ] ; then # try to compensate for / or - formats
24 | set -- $(echo $1 | sed 's/[\/\-]/ /g')
25 | fi
26 |
27 | if [ $# -ne 3 ] ; then
28 | echo "Usage: $0 month day year" >&2
29 | echo "Typical input formats are August 3 1962 and 8 3 2002" >&2
30 | exit 1
31 | fi
32 |
33 | if [ $3 -lt 99 ] ; then
34 | echo "$0: expected four-digit year value." >&2; exit 1
35 | fi
36 |
37 | if [ -z $(echo $1|sed 's/[[:digit:]]//g') ]; then
38 | monthnoToName $1
39 | else
40 | # normalize to first three letters, first upper, rest lowercase
41 | month="$(echo $1|cut -c1|tr '[:lower:]' '[:upper:]')"
42 | month="$month$(echo $1|cut -c2-3 | tr '[:upper:]' '[:lower:]')"
43 | fi
44 |
45 | echo $month $2 $3
46 |
47 | exit 0
48 |
--------------------------------------------------------------------------------
/028-convertatemp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # CONVERTATEMP - Temperature conversion script that lets the user enter
4 | # a temperature in any of Fahrenheit, Celsius or Kelvin and receive the
5 | # equivalent temperature in the other two units as the output.
6 |
7 | if uname | grep 'SunOS'>/dev/null ; then
8 | echo "Yep, SunOS, let\'s fix this baby"
9 | PATH="/usr/xpg4/bin:$PATH"
10 | fi
11 |
12 | if [ $# -eq 0 ] ; then
13 | cat << EOF >&2
14 | Usage: $0 temperature[F|C|K]
15 | where the suffix:
16 | F indicates input is in Fahrenheit (default)
17 | C indicates input is in Celsius
18 | K indicates input is in Kelvin
19 | EOF
20 | exit 1
21 | fi
22 |
23 | unit="$(echo $1|sed -e 's/[-[[:digit:]]*//g' | tr '[:lower:]' '[:upper:]' )"
24 | temp="$(echo $1|sed -e 's/[^-[[:digit:]]*//g')"
25 |
26 | case ${unit:=F}
27 | in
28 | F ) # Fahrenheit to Celsius formula: Tc = (F -32 ) / 1.8
29 | farn="$temp"
30 | cels="$(echo "scale=2;($farn - 32) / 1.8" | bc)"
31 | kelv="$(echo "scale=2;$cels + 273.15" | bc)"
32 | ;;
33 |
34 | C ) # Celsius to Fahrenheit formula: Tf = (9/5)*Tc+32
35 | cels=$temp
36 | kelv="$(echo "scale=2;$cels + 273.15" | bc)"
37 | farn="$(echo "scale=2;((9/5) * $cels) + 32" | bc)"
38 | ;;
39 |
40 | K ) # Celsius = Kelvin + 273.15, then use Cels -> Fahr formula
41 | kelv=$temp
42 | cels="$(echo "scale=2; $kelv - 273.15" | bc)"
43 | farn="$(echo "scale=2; ((9/5) * $cels) + 32" | bc)"
44 | esac
45 |
46 | echo "Fahrenheit = $farn"
47 | echo "Celsius = $cels"
48 | echo "Kelvin = $kelv"
49 |
50 | exit 0
51 |
--------------------------------------------------------------------------------
/081-ftpsyncup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # ftpsyncup - Given a target directory on an ftp server, make sure that
4 | # all new or modified files are uploaded to the remote system. Uses
5 | # a timestamp file ingeniously called .timestamp to keep track.
6 |
7 | timestamp=".timestamp"
8 | tempfile="/tmp/ftpsyncup.$$"
9 | count=0
10 |
11 | trap "/bin/rm -f $tempfile" 0 1 15 # zap tempfile on exit &sigs
12 |
13 | if [ $# -eq 0 ] ; then
14 | echo "Usage: $0 user@host { remotedir }" >&2
15 | exit 1
16 | fi
17 |
18 | user="$(echo $1 | cut -d@ -f1)"
19 | server="$(echo $1 | cut -d@ -f2)"
20 |
21 | echo "open $server" > $tempfile
22 | echo "user $user" >> $tempfile
23 |
24 | if [ $# -gt 1 ] ; then
25 | echo "cd $2" >> $tempfile
26 | fi
27 |
28 | if [ ! -f $timestamp ] ; then
29 | # no timestamp file, upload all files
30 | for filename in *
31 | do
32 | if [ -f "$filename" ] ; then
33 | echo "put \"$filename\"" >> $tempfile
34 | count=$(( $count + 1 ))
35 | fi
36 | done
37 | else
38 | for filename in $(find . -newer $timestamp -type f -print)
39 | do
40 | echo "put \"$filename\"" >> $tempfile
41 | count=$(( $count + 1 ))
42 | done
43 | fi
44 |
45 | if [ $count -eq 0 ] ; then
46 | echo "$0: No files require uploading to $server" >&2
47 | exit 0
48 | fi
49 |
50 | echo "quit" >> $tempfile
51 |
52 | echo "Synchronizing: Found $count files in local folder to upload."
53 |
54 | if ! ftp -n < $tempfile ; then
55 | echo "Done. All files synchronized up with $server"
56 | touch $timestamp
57 | fi
58 |
59 | exit 0
60 |
--------------------------------------------------------------------------------
/080-apm-footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
37 |
38 |
40 |
41 |