Odd(?) shell script practise

Hello,
I often stumble over a common shell coding practise.
Example 1:

#!/bin/sh 
# 
# Licensed Materials - Property of IBM
# Rational ClearCase
# (C) Copyright IBM Corp. 1999, 2010.  All Rights Reserved
# US Government Users Restricted Rights -
# Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp
# 
# Start/Stop ClearCase daemons as well as
# mount or umount MVFS file systems.
#
...
INSMOD="/sbin/insmod -f"
MODPROBE="/sbin/modprobe"
RMMOD=/sbin/rmmod
LSMOD=/sbin/lsmod
PIDOF=/sbin/pidof
ECHO="/bin/echo -e "
NAWK=/bin/awk
GREP=/bin/grep
RM=/bin/rm
PS=/bin/ps
CP=/bin/cp
LN=/bin/ln
MKDIR=/bin/mkdir
EXPR=/usr/bin/expr
...

Example 2:

#!/bin/ksh
# OPC_WHAT_STRING="@(#)HP Operations Smart Plug-in for Databases 11.40.000 (10/22/08)"

########################################################################
#
# File:         spi_migrate.sh
# Description:  determines the DCE / HTTPS agent environment and starts
#               migration of all available SPIs
# Language:     Bourne Shell
# Package:      -none-
#
# (c) Copyright 2004 Hewlett-Packard Development Company, L.P. 
#
########################################################################
# set -x

ECHO=echo
CAT=cat
MYSYS=`uname -s`
if [ $MYSYS = "HP-UX" ] ; then
  GREP=/usr/bin/grep
  AWK=/usr/bin/awk
  SED=/usr/bin/sed
  DIFF=/usr/bin/diff
elif [ $MYSYS = "SunOS" ] ; then
  GREP=/usr/xpg4/bin/grep
  AWK=/usr/xpg4/bin/awk
  SED=/usr/xpg4/bin/sed
  DIFF=diff
elif [ $MYSYS = "AIX" ] ; then
  GREP=/usr/bin/grep
  AWK=/usr/bin/awk
  SED=/usr/bin/sed
  DIFF=/usr/bin/diff
elif [ $MYSYS = "OSF" ] ; then
  GREP=/usr/bin/grep
  AWK=/usr/bin/awk
  SED=/usr/bin/sed
  DIFF=/usr/bin/diff
elif [ $MYSYS = "Linux" ] ; then
  GREP=grep
  AWK=awk
  DIFF=diff
  ECHO='echo -e'
...

Example3:

#! /bin/sh
#
# Log file pattern detector plugin for Nagios
# Written by Ethan Galstad (nagios@nagios.org)
# Last Modified: 07-31-1999
#
...
# Paths to commands used in this script.  These
# may have to be modified to match your system setup.
# TV: removed PATH restriction. Need to think more about what this means overall
#PATH=""

ECHO="/bin/echo"
GREP="/bin/egrep"
DIFF="/usr/bin/diff"
TAIL="/usr/bin/tail"
CAT="/bin/cat"
RM="/bin/rm"
CHMOD="/bin/chmod"
TOUCH="/bin/touch"

Do you see what is in common?
Always define all commands with its platform-dependent path and store it in UPPERCASE variables.
Sometimes I even see a for loop that finds out where a command lives and stores the result - in an UPPERCASE variable.
Always UPPERCASE!

And later in the scripts there is of course

$ECHO ... | $GREP ... | $AWK ... | $WC ...

instead of

echo ... | grep ... | awk ... | wc ...

My Questions:

  1. have you met that, too?
  2. Is there a book or a University that teaches this?

1) Yes, I've seen it a lot.
2) I'm not aware of such University either.

It's a matter of preference which in turn is driven by the known convention of capitalizing all environment variables and shell internal variables.

$CAT UUoC.txt | $GREP stuff | $CUT stuff is definitely more visible and less prone to confusion than $cat UUoC.txt | $grep stuff | $cut stuff .

It also helps when you want to throw a few extra flags into the command. Consider this for example:

SSH="$(which ssh) -o ConnectTimeout=4 -o UserKnownHostFile=stuff -o Port=12345 -o PermitLocalCommand=yes -o NoHostAuthenticationForLocalhost <...>"

I usually prefer GREP=$(which grep) or even GREP=$(which grep 2>/dev/null || echo :) if I want to be extra paranoid, but I only do this when writing shell scripts.

For compiled languages most people I know use #define kVariableName which seems to be pretty standard in C-based languages (I only use Obj-C though).

It is fairly common practice when writing software that is to be used in multiple operating environments to use a scheme like one of these as a configuration option when installing the software. Obviously the copyrighted code in example 2 from HP configures itself each time the script runs based on the results of a call to uname. How the IBM script in example 1 and the nagios script in example 3 are setup may be hidden in the ... areas of the code you didn't show or during the installation of these scripts.

I don't know of any university course that teaches this style, but you can bet that HP, IBM, and Oracle have coding guidelines (and probably internal classes) that specify coding styles for these kinds of application scripts.

I like...

Although not quite the same........

Stragely enough I try to use capitalisation whenever I can, even when coding is case insensitive:-

http://www.unix.com/windows-dos-issues-discussions/220373-sox-1khz-sinewave-generator-using-batch-file.html

But this idea I like...

<Thumbs up>

Some of the ... code in the IBM script:

LISTVIEWUSERS="${FUSER} -m `ls -d $VIEWPATH/* 2>/dev/null` `${MOUNT} -t mvfs |${NAWK} '{print $3}'`"
...
PIDLIST=`${ECHO} ${OTHERPIDS} ${VIEWUSERPIDS} ${SETVIEWPIDS} | ${TR} ' ^I' "${NEWLINE}${NEWLINE}" | ${SORT} -u`

The even forgot about the ls . The ^I is a literal TAB character.
I would write that as

LISTVIEWUSERS="fuser -m `ls -d $VIEWPATH/* 2>/dev/null` `mount -t mvfs | awk '{print $3}'`"
...
PIDLIST=`echo ${OTHERPIDS} ${VIEWUSERPIDS} ${SETVIEWPIDS} | tr ' \t' "${NEWLINE}${NEWLINE}" | sort -u`

and at the beginning of the script only put a general

export PATH
PATH=/usr/xpg4/bin:/bin:/usr/bin:/usr/sbin:/sbin