536 lines
9.2 KiB
HTML
536 lines
9.2 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Unofficial Shell Scripting Stylesheet</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="Advanced Bash-Scripting Guide"
|
|
HREF="index.html"><LINK
|
|
REL="UP"
|
|
TITLE="Scripting With Style"
|
|
HREF="scrstyle.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Scripting With Style"
|
|
HREF="scrstyle.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Miscellany"
|
|
HREF="miscellany.html"></HEAD
|
|
><BODY
|
|
CLASS="SECT1"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Advanced Bash-Scripting Guide: </TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="scrstyle.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
>Chapter 35. Scripting With Style</TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="miscellany.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="UNOFFICIALST"
|
|
></A
|
|
>35.1. Unofficial Shell Scripting Stylesheet</H1
|
|
><P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>Comment your code. This makes it easier for others to
|
|
understand (and appreciate), and easier for you to maintain.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
|
|
# It made perfect sense when you wrote it last year,
|
|
#+ but now it's a complete mystery.
|
|
# (From Antek Sawicki's "pw.sh" script.)</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Add descriptive headers to your scripts and functions.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
|
|
#************************************************#
|
|
# xyz.sh #
|
|
# written by Bozo Bozeman #
|
|
# July 05, 2001 #
|
|
# #
|
|
# Clean up project files. #
|
|
#************************************************#
|
|
|
|
E_BADDIR=85 # No such directory.
|
|
projectdir=/home/bozo/projects # Directory to clean up.
|
|
|
|
# --------------------------------------------------------- #
|
|
# cleanup_pfiles () #
|
|
# Removes all files in designated directory. #
|
|
# Parameter: $target_directory #
|
|
# Returns: 0 on success, $E_BADDIR if something went wrong. #
|
|
# --------------------------------------------------------- #
|
|
cleanup_pfiles ()
|
|
{
|
|
if [ ! -d "$1" ] # Test if target directory exists.
|
|
then
|
|
echo "$1 is not a directory."
|
|
return $E_BADDIR
|
|
fi
|
|
|
|
rm -f "$1"/*
|
|
return 0 # Success.
|
|
}
|
|
|
|
cleanup_pfiles $projectdir
|
|
|
|
exit $?</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Avoid using <SPAN
|
|
CLASS="QUOTE"
|
|
>"magic numbers,"</SPAN
|
|
>
|
|
|
|
<A
|
|
NAME="AEN20041"
|
|
HREF="#FTN.AEN20041"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
>
|
|
|
|
that is, <SPAN
|
|
CLASS="QUOTE"
|
|
>"hard-wired"</SPAN
|
|
> literal constants. Use
|
|
meaningful variable names instead. This makes the script
|
|
easier to understand and permits making changes and updates
|
|
without breaking the application.
|
|
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>if [ -f /var/log/messages ]
|
|
then
|
|
...
|
|
fi
|
|
# A year later, you decide to change the script to check /var/log/syslog.
|
|
# It is now necessary to manually change the script, instance by instance,
|
|
#+ and hope nothing breaks.
|
|
|
|
# A better way:
|
|
LOGFILE=/var/log/messages # Only line that needs to be changed.
|
|
if [ -f "$LOGFILE" ]
|
|
then
|
|
...
|
|
fi</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Choose descriptive names for variables and functions.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>fl=`ls -al $dirname` # Cryptic.
|
|
file_listing=`ls -al $dirname` # Better.
|
|
|
|
|
|
MAXVAL=10 # All caps used for a script constant.
|
|
while [ "$index" -le "$MAXVAL" ]
|
|
...
|
|
|
|
|
|
E_NOTFOUND=95 # Uppercase for an errorcode,
|
|
#+ and name prefixed with E_.
|
|
if [ ! -e "$filename" ]
|
|
then
|
|
echo "File $filename not found."
|
|
exit $E_NOTFOUND
|
|
fi
|
|
|
|
|
|
MAIL_DIRECTORY=/var/spool/mail/bozo # Uppercase for an environmental
|
|
export MAIL_DIRECTORY #+ variable.
|
|
|
|
|
|
GetAnswer () # Mixed case works well for a
|
|
{ #+ function name, especially
|
|
prompt=$1 #+ when it improves legibility.
|
|
echo -n $prompt
|
|
read answer
|
|
return $answer
|
|
}
|
|
|
|
GetAnswer "What is your favorite number? "
|
|
favorite_number=$?
|
|
echo $favorite_number
|
|
|
|
|
|
_uservariable=23 # Permissible, but not recommended.
|
|
# It's better for user-defined variables not to start with an underscore.
|
|
# Leave that for system variables.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Use <A
|
|
HREF="exit-status.html#EXITCOMMANDREF"
|
|
>exit codes</A
|
|
>
|
|
in a systematic and meaningful way.
|
|
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>E_WRONG_ARGS=95
|
|
...
|
|
...
|
|
exit $E_WRONG_ARGS</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
See also <A
|
|
HREF="exitcodes.html"
|
|
>Appendix E</A
|
|
>.</P
|
|
><P
|
|
><EM
|
|
>Ender</EM
|
|
> suggests using the <A
|
|
HREF="exitcodes.html#SYSEXITSREF"
|
|
>exit codes
|
|
in <TT
|
|
CLASS="FILENAME"
|
|
>/usr/include/sysexits.h</TT
|
|
></A
|
|
> in shell
|
|
scripts, though these are primarily intended for C and C++
|
|
programming.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Use standardized parameter flags for script invocation.
|
|
<EM
|
|
>Ender</EM
|
|
> proposes the following set
|
|
of flags.</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>-a All: Return all information (including hidden file info).
|
|
-b Brief: Short version, usually for other scripts.
|
|
-c Copy, concatenate, etc.
|
|
-d Daily: Use information from the whole day, and not merely
|
|
information for a specific instance/user.
|
|
-e Extended/Elaborate: (often does not include hidden file info).
|
|
-h Help: Verbose usage w/descs, aux info, discussion, help.
|
|
See also -V.
|
|
-l Log output of script.
|
|
-m Manual: Launch man-page for base command.
|
|
-n Numbers: Numerical data only.
|
|
-r Recursive: All files in a directory (and/or all sub-dirs).
|
|
-s Setup & File Maintenance: Config files for this script.
|
|
-u Usage: List of invocation flags for the script.
|
|
-v Verbose: Human readable output, more or less formatted.
|
|
-V Version / License / Copy(right|left) / Contribs (email too).</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>See also <A
|
|
HREF="standard-options.html"
|
|
>Section G.1</A
|
|
>.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Break complex scripts into simpler modules. Use functions
|
|
where appropriate. See <A
|
|
HREF="bashver2.html#CARDS"
|
|
>Example 37-4</A
|
|
>.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Don't use a complex construct where a simpler one will do.
|
|
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>COMMAND
|
|
if [ $? -eq 0 ]
|
|
...
|
|
# Redundant and non-intuitive.
|
|
|
|
if COMMAND
|
|
...
|
|
# More concise (if perhaps not quite as legible).</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></LI
|
|
></UL
|
|
><TABLE
|
|
BORDER="0"
|
|
WIDTH="100%"
|
|
CELLSPACING="0"
|
|
CELLPADDING="0"
|
|
CLASS="EPIGRAPH"
|
|
><TR
|
|
><TD
|
|
WIDTH="45%"
|
|
> </TD
|
|
><TD
|
|
WIDTH="45%"
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><I
|
|
><P
|
|
><I
|
|
>... reading the UNIX source code to the Bourne shell (/bin/sh). I
|
|
was shocked at how much simple algorithms could be made cryptic, and
|
|
therefore useless, by a poor choice of code style. I asked myself,
|
|
<SPAN
|
|
CLASS="QUOTE"
|
|
>"Could someone be proud of this code?"</SPAN
|
|
></I
|
|
></P
|
|
><P
|
|
><I
|
|
>--Landon Noll</I
|
|
></P
|
|
></I
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><H3
|
|
CLASS="FOOTNOTES"
|
|
>Notes</H3
|
|
><TABLE
|
|
BORDER="0"
|
|
CLASS="FOOTNOTES"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN20041"
|
|
HREF="unofficialst.html#AEN20041"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>In this context, <SPAN
|
|
CLASS="QUOTE"
|
|
>"magic
|
|
numbers"</SPAN
|
|
> have an entirely different meaning than
|
|
the <A
|
|
HREF="sha-bang.html#MAGNUMREF"
|
|
>magic numbers</A
|
|
> used
|
|
to designate file types.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="scrstyle.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="miscellany.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Scripting With Style</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="scrstyle.html"
|
|
ACCESSKEY="U"
|
|
>Up</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Miscellany</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |