old-www/LDP/abs/html/extmisc.html

3002 lines
46 KiB
HTML
Raw Permalink Blame History

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML
><HEAD
><TITLE
>Miscellaneous Commands</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="External Filters, Programs and Commands"
HREF="external.html"><LINK
REL="PREVIOUS"
TITLE="Math Commands"
HREF="mathc.html"><LINK
REL="NEXT"
TITLE="System and Administrative Commands"
HREF="system.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="mathc.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Chapter 16. External Filters, Programs and Commands</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="system.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="EXTMISC"
></A
>16.9. Miscellaneous Commands</H1
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
><A
NAME="MISCCOMMANDLISTING1"
></A
>Command that fit in no
special category</B
></P
><DL
><DT
><A
NAME="JOTREF"
></A
><B
CLASS="COMMAND"
>jot</B
>, <A
NAME="SEQREF"
></A
><B
CLASS="COMMAND"
>seq</B
></DT
><DD
><P
>These utilities emit a sequence of integers, with a
user-selectable increment.</P
><P
>The default separator character between each integer is a
newline, but this can be changed with the <TT
CLASS="OPTION"
>-s</TT
>
option.</P
><P
> <TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>seq 5</B
></TT
>
<TT
CLASS="COMPUTEROUTPUT"
>1
2
3
4
5</TT
>
<TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>seq -s : 5</B
></TT
>
<TT
CLASS="COMPUTEROUTPUT"
>1:2:3:4:5</TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>Both <B
CLASS="COMMAND"
>jot</B
> and <B
CLASS="COMMAND"
>seq</B
>
come in handy in a <A
HREF="loops1.html#FORLOOPREF1"
>for
loop</A
>.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="EX53"
></A
><P
><B
>Example 16-54. Using <I
CLASS="FIRSTTERM"
>seq</I
> to generate loop
arguments</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# Using "seq"
echo
for a in `seq 80` # or for a in $( seq 80 )
# Same as for a in 1 2 3 4 5 ... 80 (saves much typing!).
# May also use 'jot' (if present on system).
do
echo -n "$a "
done # 1 2 3 4 5 ... 80
# Example of using the output of a command to generate
# the [list] in a "for" loop.
echo; echo
COUNT=80 # Yes, 'seq' also accepts a replaceable parameter.
for a in `seq $COUNT` # or for a in $( seq $COUNT )
do
echo -n "$a "
done # 1 2 3 4 5 ... 80
echo; echo
BEGIN=75
END=80
for a in `seq $BEGIN $END`
# Giving "seq" two arguments starts the count at the first one,
#+ and continues until it reaches the second.
do
echo -n "$a "
done # 75 76 77 78 79 80
echo; echo
BEGIN=45
INTERVAL=5
END=80
for a in `seq $BEGIN $INTERVAL $END`
# Giving "seq" three arguments starts the count at the first one,
#+ uses the second for a step interval,
#+ and continues until it reaches the third.
do
echo -n "$a "
done # 45 50 55 60 65 70 75 80
echo; echo
exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
>A simpler example:</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
># Create a set of 10 files,
#+ named file.1, file.2 . . . file.10.
COUNT=10
PREFIX=file
for filename in `seq $COUNT`
do
touch $PREFIX.$filename
# Or, can do other operations,
#+ such as rm, grep, etc.
done</PRE
></FONT
></TD
></TR
></TABLE
></P
><DIV
CLASS="EXAMPLE"
><A
NAME="LETTERCOUNT"
></A
><P
><B
>Example 16-55. Letter Count"</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# letter-count.sh: Counting letter occurrences in a text file.
# Written by Stefano Palmeri.
# Used in ABS Guide with permission.
# Slightly modified by document author.
MINARGS=2 # Script requires at least two arguments.
E_BADARGS=65
FILE=$1
let LETTERS=$#-1 # How many letters specified (as command-line args).
# (Subtract 1 from number of command-line args.)
show_help(){
echo
echo Usage: `basename $0` file letters
echo Note: `basename $0` arguments are case sensitive.
echo Example: `basename $0` foobar.txt G n U L i N U x.
echo
}
# Checks number of arguments.
if [ $# -lt $MINARGS ]; then
echo
echo "Not enough arguments."
echo
show_help
exit $E_BADARGS
fi
# Checks if file exists.
if [ ! -f $FILE ]; then
echo "File \"$FILE\" does not exist."
exit $E_BADARGS
fi
# Counts letter occurrences .
for n in `seq $LETTERS`; do
shift
if [[ `echo -n "$1" | wc -c` -eq 1 ]]; then # Checks arg.
echo "$1" -\&#62; `cat $FILE | tr -cd "$1" | wc -c` # Counting.
else
echo "$1 is not a single char."
fi
done
exit $?
# This script has exactly the same functionality as letter-count2.sh,
#+ but executes faster.
# Why?</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="90%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>Somewhat more capable than <I
CLASS="FIRSTTERM"
>seq</I
>,
<B
CLASS="COMMAND"
>jot</B
> is a classic UNIX
utility that is not normally included in a standard Linux
distro. However, the source <I
CLASS="FIRSTTERM"
>rpm</I
>
is available for download from the <A
HREF="http://www.mit.edu/afs/athena/system/rhlinux/athena-9.0/free/SRPMS/athena-jot-9.0-3.src.rpm"
TARGET="_top"
> MIT repository</A
>.</P
><P
><A
NAME="JOTRANDOM"
></A
></P
><P
>Unlike <I
CLASS="FIRSTTERM"
>seq</I
>, <B
CLASS="COMMAND"
>jot</B
> can
generate a sequence of random numbers, using the <TT
CLASS="OPTION"
>-r</TT
>
option.</P
><P
><TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>jot -r 3 999</B
></TT
>
<TT
CLASS="COMPUTEROUTPUT"
>1069
1272
1428</TT
></PRE
></FONT
></TD
></TR
></TABLE
></P
></TD
></TR
></TABLE
></DIV
></DD
><DT
><A
NAME="GETOPTY"
></A
><B
CLASS="COMMAND"
>getopt</B
></DT
><DD
><P
>The <B
CLASS="COMMAND"
>getopt</B
> command
parses command-line options preceded by a <A
HREF="special-chars.html#DASHREF"
>dash</A
>. This external command
corresponds to the <A
HREF="internal.html#GETOPTSX"
>getopts</A
>
Bash builtin. Using <B
CLASS="COMMAND"
>getopt</B
> permits
handling long options by means of the <TT
CLASS="OPTION"
>-l</TT
>
flag, and this also allows parameter reshuffling.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="EX33A"
></A
><P
><B
>Example 16-56. Using <I
CLASS="FIRSTTERM"
>getopt</I
> to parse command-line
options</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# Using getopt
# Try the following when invoking this script:
# sh ex33a.sh -a
# sh ex33a.sh -abc
# sh ex33a.sh -a -b -c
# sh ex33a.sh -d
# sh ex33a.sh -dXYZ
# sh ex33a.sh -d XYZ
# sh ex33a.sh -abcd
# sh ex33a.sh -abcdZ
# sh ex33a.sh -z
# sh ex33a.sh a
# Explain the results of each of the above.
E_OPTERR=65
if [ "$#" -eq 0 ]
then # Script needs at least one command-line argument.
echo "Usage $0 -[options a,b,c]"
exit $E_OPTERR
fi
set -- `getopt "abcd:" "$@"`
# Sets positional parameters to command-line arguments.
# What happens if you use "$*" instead of "$@"?
while [ ! -z "$1" ]
do
case "$1" in
-a) echo "Option \"a\"";;
-b) echo "Option \"b\"";;
-c) echo "Option \"c\"";;
-d) echo "Option \"d\" $2";;
*) break;;
esac
shift
done
# It is usually better to use the 'getopts' builtin in a script.
# See "ex33.sh."
exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="90%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>As <EM
>Peggy Russell</EM
> points out:</P
><P
>It is often necessary to include an <A
HREF="internal.html#EVALREF"
>eval</A
> to correctly process
<A
HREF="special-chars.html#WHITESPACEREF"
>whitespace</A
> and
<I
CLASS="FIRSTTERM"
>quotes</I
>.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>args=$(getopt -o a:bc:d -- "$@")
eval set -- "$args"</PRE
></FONT
></TD
></TR
></TABLE
></P
></TD
></TR
></TABLE
></DIV
><P
>See <A
HREF="string-manipulation.html#GETOPTSIMPLE"
>Example 10-5</A
> for a simplified emulation
of <B
CLASS="COMMAND"
>getopt</B
>.</P
></DD
><DT
><A
NAME="RUNPARTSREF"
></A
><B
CLASS="COMMAND"
>run-parts</B
></DT
><DD
><P
>The <B
CLASS="COMMAND"
>run-parts</B
> command
<A
NAME="AEN14105"
HREF="#FTN.AEN14105"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
>
executes all the scripts in a target directory, sequentially
in ASCII-sorted filename order. Of course, the scripts
need to have execute permission.</P
><P
>The <A
HREF="system.html#CRONREF"
>cron</A
> <A
HREF="communications.html#DAEMONREF"
>daemon</A
> invokes
<B
CLASS="COMMAND"
>run-parts</B
> to run the scripts in
the <TT
CLASS="FILENAME"
>/etc/cron.*</TT
>
directories.</P
></DD
><DT
><A
NAME="YESREF"
></A
><B
CLASS="COMMAND"
>yes</B
></DT
><DD
><P
>In its default behavior the <B
CLASS="COMMAND"
>yes</B
>
command feeds a continuous string of the character
<TT
CLASS="COMPUTEROUTPUT"
>y</TT
> followed
by a line feed to <TT
CLASS="FILENAME"
>stdout</TT
>. A
<B
CLASS="KEYCAP"
>control</B
>-<B
CLASS="KEYCAP"
>C</B
>
terminates the run. A different output string
may be specified, as in <TT
CLASS="USERINPUT"
><B
>yes different
string</B
></TT
>, which would continually output
<TT
CLASS="COMPUTEROUTPUT"
>different string</TT
> to
<TT
CLASS="FILENAME"
>stdout</TT
>.</P
><P
>One might well ask the purpose of this. From the
command-line or in a script, the output of
<B
CLASS="COMMAND"
>yes</B
> can be redirected or piped into a
program expecting user input. In effect, this becomes a sort
of poor man's version of <I
CLASS="FIRSTTERM"
>expect</I
>.</P
><P
><TT
CLASS="USERINPUT"
><B
>yes | fsck /dev/hda1</B
></TT
> runs
<B
CLASS="COMMAND"
>fsck</B
> non-interactively (careful!).</P
><P
><TT
CLASS="USERINPUT"
><B
>yes | rm -r dirname</B
></TT
> has same effect as
<TT
CLASS="USERINPUT"
><B
>rm -rf dirname</B
></TT
> (careful!).</P
><DIV
CLASS="WARNING"
><P
></P
><TABLE
CLASS="WARNING"
WIDTH="90%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/warning.gif"
HSPACE="5"
ALT="Warning"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>Caution advised when piping
<I
CLASS="FIRSTTERM"
>yes</I
> to a potentially dangerous
system command, such as <A
HREF="system.html#FSCKREF"
>fsck</A
>
or <A
HREF="system.html#FDISKREF"
>fdisk</A
>. It might have
unintended consequences.</P
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="90%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>The <I
CLASS="FIRSTTERM"
>yes</I
> command parses variables,
or more accurately, it echoes parsed variables.
For example:</P
><P
> <TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>yes $BASH_VERSION</B
></TT
>
<TT
CLASS="COMPUTEROUTPUT"
>3.1.17(1)-release
3.1.17(1)-release
3.1.17(1)-release
3.1.17(1)-release
3.1.17(1)-release
. . .</TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
> This particular <SPAN
CLASS="QUOTE"
>"feature"</SPAN
> may be used
to create a <EM
>very large</EM
> ASCII file on the fly:
<TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>yes $PATH &#62; huge_file.txt</B
></TT
>
<TT
CLASS="USERINPUT"
><B
>Ctl-C</B
></TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
Hit <TT
CLASS="USERINPUT"
><B
>Ctl-C</B
></TT
> <EM
>very
quickly</EM
>, or you just might get more than you
bargained for. . . .
</P
></TD
></TR
></TABLE
></DIV
><P
><A
NAME="YESEMU"
></A
>The <I
CLASS="FIRSTTERM"
>yes</I
>
command may be emulated in a very simple script <A
HREF="functions.html#FUNCTIONREF"
>function</A
>.</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>yes ()
{ # Trivial emulation of "yes" ...
local DEFAULT_TEXT="y"
while [ true ] # Endless loop.
do
if [ -z "$1" ]
then
echo "$DEFAULT_TEXT"
else # If argument ...
echo "$1" # ... expand and echo it.
fi
done # The only things missing are the
} #+ --help and --version options.</PRE
></FONT
></TD
></TR
></TABLE
></P
></DD
><DT
><A
NAME="BANNERREF"
></A
><B
CLASS="COMMAND"
>banner</B
></DT
><DD
><P
>Prints arguments as a large vertical banner to
<TT
CLASS="FILENAME"
>stdout</TT
>, using an <A
HREF="special-chars.html#ASCIIDEF"
>ASCII</A
> character (default
'#'). This may be redirected to a printer for
hardcopy.</P
><P
>Note that <I
CLASS="FIRSTTERM"
>banner</I
> has been
dropped from many Linux distros, presumably because it
is no longer considered useful.</P
></DD
><DT
><A
NAME="PRINTENVREF"
></A
><B
CLASS="COMMAND"
>printenv</B
></DT
><DD
><P
>Show all the <A
HREF="othertypesv.html#ENVREF"
>environmental
variables</A
> set for a particular user.</P
><P
> <TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>printenv | grep HOME</B
></TT
>
<TT
CLASS="COMPUTEROUTPUT"
>HOME=/home/bozo</TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DD
><DT
><A
NAME="LPREF"
></A
><B
CLASS="COMMAND"
>lp</B
></DT
><DD
><P
>The <B
CLASS="COMMAND"
>lp</B
> and <B
CLASS="COMMAND"
>lpr</B
>
commands send file(s) to the print queue, to be printed as
hard copy.
<A
NAME="AEN14214"
HREF="#FTN.AEN14214"
><SPAN
CLASS="footnote"
>[2]</SPAN
></A
>
These commands trace the origin of their names to the
line printers of another era.
<A
NAME="AEN14218"
HREF="#FTN.AEN14218"
><SPAN
CLASS="footnote"
>[3]</SPAN
></A
>
</P
><P
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>lp file1.txt</B
></TT
>
or <TT
CLASS="PROMPT"
>bash </TT
><TT
CLASS="USERINPUT"
><B
>lp
&#60;file1.txt</B
></TT
></P
><P
>It is often useful to pipe the formatted output from
<B
CLASS="COMMAND"
>pr</B
> to <B
CLASS="COMMAND"
>lp</B
>.</P
><P
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>pr -options file1.txt | lp</B
></TT
>
</P
><P
>Formatting packages, such as <A
HREF="textproc.html#GROFFREF"
>groff</A
> and
<I
CLASS="FIRSTTERM"
>Ghostscript</I
> may send their output
directly to <B
CLASS="COMMAND"
>lp</B
>.</P
><P
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>groff -Tascii file.tr | lp</B
></TT
>
</P
><P
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>gs -options | lp file.ps</B
></TT
>
</P
><P
>Related commands are <B
CLASS="COMMAND"
>lpq</B
>, for viewing
the print queue, and <B
CLASS="COMMAND"
>lprm</B
>, for removing
jobs from the print queue.</P
></DD
><DT
><A
NAME="TEEREF"
></A
><B
CLASS="COMMAND"
>tee</B
></DT
><DD
><P
>[UNIX borrows an idea from the plumbing trade.]</P
><P
>This is a redirection operator, but with a difference. Like the
plumber's <I
CLASS="FIRSTTERM"
>tee,</I
> it permits <SPAN
CLASS="QUOTE"
>"siphoning
off"</SPAN
> <EM
>to a file </EM
>the output of a command
or commands within a pipe, but without affecting the result. This is
useful for printing an ongoing process to a file or paper, perhaps to
keep track of it for debugging purposes.</P
><TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
> (redirection)
|----&#62; to file
|
==========================|====================
command ---&#62; command ---&#62; |tee ---&#62; command ---&#62; ---&#62; output of pipe
===============================================
</PRE
></FONT
></TD
></TR
></TABLE
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>cat listfile* | sort | tee check.file | uniq &#62; result.file
# ^^^^^^^^^^^^^^ ^^^^
# The file "check.file" contains the concatenated sorted "listfiles,"
#+ before the duplicate lines are removed by 'uniq.'</PRE
></FONT
></TD
></TR
></TABLE
></P
></DD
><DT
><A
NAME="MKFIFOREF"
></A
><B
CLASS="COMMAND"
>mkfifo</B
></DT
><DD
><P
><A
NAME="NAMEDPIPEREF"
></A
>This obscure command
creates a <I
CLASS="FIRSTTERM"
>named pipe</I
>, a temporary
<I
CLASS="FIRSTTERM"
>first-in-first-out buffer</I
> for
transferring data between processes.
<A
NAME="AEN14280"
HREF="#FTN.AEN14280"
><SPAN
CLASS="footnote"
>[4]</SPAN
></A
>
Typically, one process writes to the FIFO, and the other
reads from it. See <A
HREF="contributed-scripts.html#FIFO"
>Example A-14</A
>.</P
><P
> <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# This short script by Omair Eshkenazi.
# Used in ABS Guide with permission (thanks!).
mkfifo pipe1 # Yes, pipes can be given names.
mkfifo pipe2 # Hence the designation "named pipe."
(cut -d' ' -f1 | tr "a-z" "A-Z") &#62;pipe2 &#60;pipe1 &#38;
ls -l | tr -s ' ' | cut -d' ' -f3,9- | tee pipe1 |
cut -d' ' -f2 | paste - pipe2
rm -f pipe1
rm -f pipe2
# No need to kill background processes when script terminates (why not?).
exit $?
Now, invoke the script and explain the output:
sh mkfifo-example.sh
4830.tar.gz BOZO
pipe1 BOZO
pipe2 BOZO
mkfifo-example.sh BOZO
Mixed.msg BOZO</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DD
><DT
><A
NAME="PATHCHKREF"
></A
><B
CLASS="COMMAND"
>pathchk</B
></DT
><DD
><P
>This command checks the validity of a filename. If the
filename exceeds the maximum allowable length (255
characters) or one or more of the directories in
its path is not searchable, then an error message
results.</P
><P
>Unfortunately, <B
CLASS="COMMAND"
>pathchk</B
> does
not return a recognizable error code, and it is therefore
pretty much useless in a script. Consider instead the
<A
HREF="fto.html#RTIF"
>file test operators</A
>.</P
></DD
><DT
><A
NAME="DDREF"
></A
><B
CLASS="COMMAND"
>dd</B
></DT
><DD
><P
>Though this somewhat obscure and much feared
<B
CLASS="COMMAND"
>d</B
>ata <B
CLASS="COMMAND"
>d</B
>uplicator
command originated as a utility for exchanging
data on magnetic tapes between UNIX minicomputers
and IBM mainframes, it still has its uses.
The <B
CLASS="COMMAND"
>dd</B
> command simply copies a
file (or <TT
CLASS="FILENAME"
>stdin/stdout</TT
>), but with
conversions. <A
NAME="DDCONVERSIONS"
></A
>Possible conversions
include ASCII/EBCDIC,
<A
NAME="AEN14318"
HREF="#FTN.AEN14318"
><SPAN
CLASS="footnote"
>[5]</SPAN
></A
>
upper/lower case, swapping of byte pairs between input
and output, and skipping and/or truncating the head or
tail of the input file.</P
><P
> <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
># Converting a file to all uppercase:
dd if=$filename conv=ucase &#62; $filename.uppercase
# lcase # For lower case conversion</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
><A
NAME="DDOPTIONS"
></A
></P
><P
>Some basic options to <B
CLASS="COMMAND"
>dd</B
> are:
<P
></P
><UL
><LI
><P
>if=INFILE</P
><P
>INFILE is the <I
CLASS="FIRSTTERM"
>source</I
>
file.</P
></LI
><LI
><P
>of=OUTFILE</P
><P
>OUTFILE is the <I
CLASS="FIRSTTERM"
>target</I
>
file, the file that will have the data written to it.</P
></LI
><LI
><P
>bs=BLOCKSIZE</P
><P
>This is the size of each block of data being read
and written, usually a power of 2.</P
></LI
><LI
><P
>skip=BLOCKS</P
><P
>How many blocks of data to skip in INFILE before
starting to copy. This is useful when the INFILE has
<SPAN
CLASS="QUOTE"
>"garbage"</SPAN
> or garbled data in its
header or when it is desirable to copy only a portion
of the INFILE.</P
></LI
><LI
><P
>seek=BLOCKS</P
><P
>How many blocks of data to skip in OUTFILE before
starting to copy, leaving blank data at beginning
of OUTFILE.</P
></LI
><LI
><P
>count=BLOCKS</P
><P
>Copy only this many blocks of data, rather than the
entire INFILE.</P
></LI
><LI
><P
>conv=CONVERSION</P
><P
>Type of conversion to be applied to INFILE data
before copying operation.</P
></LI
></UL
>
</P
><P
>A <TT
CLASS="USERINPUT"
><B
>dd --help</B
></TT
> lists all the
options this powerful utility takes.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="SELFCOPY"
></A
><P
><B
>Example 16-57. A script that copies itself</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# self-copy.sh
# This script copies itself.
file_subscript=copy
dd if=$0 of=$0.$file_subscript 2&#62;/dev/null
# Suppress messages from dd: ^^^^^^^^^^^
exit $?
# A program whose only output is its own source code
#+ is called a "quine" per Willard Quine.
# Does this script qualify as a quine?</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="EXERCISINGDD"
></A
><P
><B
>Example 16-58. Exercising <I
CLASS="FIRSTTERM"
>dd</I
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# exercising-dd.sh
# Script by Stephane Chazelas.
# Somewhat modified by ABS Guide author.
infile=$0 # This script.
outfile=log.txt # Output file left behind.
n=8
p=11
dd if=$infile of=$outfile bs=1 skip=$((n-1)) count=$((p-n+1)) 2&#62; /dev/null
# Extracts characters n to p (8 to 11) from this script ("bash").
# ----------------------------------------------------------------
echo -n "hello vertical world" | dd cbs=1 conv=unblock 2&#62; /dev/null
# Echoes "hello vertical world" vertically downward.
# Why? A newline follows each character dd emits.
exit $?</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
><A
NAME="DDKEYSTROKES"
></A
></P
><P
>To demonstrate just how versatile <B
CLASS="COMMAND"
>dd</B
> is,
let's use it to capture keystrokes.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="DDKEYPRESS"
></A
><P
><B
>Example 16-59. Capturing Keystrokes</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# dd-keypress.sh: Capture keystrokes without needing to press ENTER.
keypresses=4 # Number of keypresses to capture.
old_tty_setting=$(stty -g) # Save old terminal settings.
echo "Press $keypresses keys."
stty -icanon -echo # Disable canonical mode.
# Disable local echo.
keys=$(dd bs=1 count=$keypresses 2&#62; /dev/null)
# 'dd' uses stdin, if "if" (input file) not specified.
stty "$old_tty_setting" # Restore old terminal settings.
echo "You pressed the \"$keys\" keys."
# Thanks, Stephane Chazelas, for showing the way.
exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
><A
NAME="DDRANDOM"
></A
></P
><P
>The <B
CLASS="COMMAND"
>dd</B
> command can do random access on a
data stream.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>echo -n . | dd bs=1 seek=4 of=file conv=notrunc
# The "conv=notrunc" option means that the output file
#+ will not be truncated.
# Thanks, S.C.</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
><A
NAME="DDCOPY"
></A
></P
><P
>The <B
CLASS="COMMAND"
>dd</B
> command can copy raw data
and disk images to and from devices, such as floppies and
tape drives (<A
HREF="contributed-scripts.html#COPYCD"
>Example A-5</A
>). A common use is
creating boot floppies.</P
><P
> <TT
CLASS="USERINPUT"
><B
>dd if=kernel-image of=/dev/fd0H1440</B
></TT
>
</P
><P
>Similarly, <B
CLASS="COMMAND"
>dd</B
> can copy the entire
contents of a floppy, even one formatted with a
<SPAN
CLASS="QUOTE"
>"foreign"</SPAN
> OS, to the hard drive as an
image file.</P
><P
> <TT
CLASS="USERINPUT"
><B
>dd if=/dev/fd0 of=/home/bozo/projects/floppy.img</B
></TT
>
</P
><P
><A
NAME="BFS"
></A
>Likewise, <B
CLASS="COMMAND"
>dd</B
>
can create bootable flash drives and SD cards.</P
><P
><TT
CLASS="USERINPUT"
><B
>dd if=image.iso of=/dev/sdb</B
></TT
></P
><P
><A
NAME="RPSDCARD01"
></A
></P
><DIV
CLASS="EXAMPLE"
><A
NAME="RPSDCARD"
></A
><P
><B
>Example 16-60. Preparing a bootable SD card for the
<EM
>Raspberry Pi</EM
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# rp.sdcard.sh
# Preparing an SD card with a bootable image for the Raspberry Pi.
# $1 = imagefile name
# $2 = sdcard (device file)
# Otherwise defaults to the defaults, see below.
DEFAULTbs=4M # Block size, 4 mb default.
DEFAULTif="2013-07-26-wheezy-raspbian.img" # Commonly used distro.
DEFAULTsdcard="/dev/mmcblk0" # May be different. Check!
ROOTUSER_NAME=root # Must run as root!
E_NOTROOT=81
E_NOIMAGE=82
username=$(id -nu) # Who is running this script?
if [ "$username" != "$ROOTUSER_NAME" ]
then
echo "This script must run as root or with root privileges."
exit $E_NOTROOT
fi
if [ -n "$1" ]
then
imagefile="$1"
else
imagefile="$DEFAULTif"
fi
if [ -n "$2" ]
then
sdcard="$2"
else
sdcard="$DEFAULTsdcard"
fi
if [ ! -e $imagefile ]
then
echo "Image file \"$imagefile\" not found!"
exit $E_NOIMAGE
fi
echo "Last chance to change your mind!"; echo
read -s -n1 -p "Hit a key to write $imagefile to $sdcard [Ctl-c to exit]."
echo; echo
echo "Writing $imagefile to $sdcard ..."
dd bs=$DEFAULTbs if=$imagefile of=$sdcard
exit $?
# Exercises:
# ---------
# 1) Provide additional error checking.
# 2) Have script autodetect device file for SD card (difficult!).
# 3) Have script sutodetect image file (*img) in $PWD.</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
><A
NAME="DDSWAP"
></A
></P
><P
> Other applications of <B
CLASS="COMMAND"
>dd</B
> include
initializing temporary swap files (<A
HREF="zeros.html#EX73"
>Example 31-2</A
>)
and ramdisks (<A
HREF="zeros.html#RAMDISK"
>Example 31-3</A
>). It can even do a
low-level copy of an entire hard drive partition, although
this is not necessarily recommended.</P
><P
>People (with presumably nothing better to do with
their time) are constantly thinking of interesting
applications of <B
CLASS="COMMAND"
>dd</B
>.</P
><P
><A
NAME="DDFDEL"
></A
></P
><DIV
CLASS="EXAMPLE"
><A
NAME="BLOTOUT"
></A
><P
><B
>Example 16-61. Securely deleting a file</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# blot-out.sh: Erase "all" traces of a file.
# This script overwrites a target file alternately
#+ with random bytes, then zeros before finally deleting it.
# After that, even examining the raw disk sectors by conventional methods
#+ will not reveal the original file data.
PASSES=7 # Number of file-shredding passes.
# Increasing this slows script execution,
#+ especially on large target files.
BLOCKSIZE=1 # I/O with /dev/urandom requires unit block size,
#+ otherwise you get weird results.
E_BADARGS=70 # Various error exit codes.
E_NOT_FOUND=71
E_CHANGED_MIND=72
if [ -z "$1" ] # No filename specified.
then
echo "Usage: `basename $0` filename"
exit $E_BADARGS
fi
file=$1
if [ ! -e "$file" ]
then
echo "File \"$file\" not found."
exit $E_NOT_FOUND
fi
echo; echo -n "Are you absolutely sure you want to blot out \"$file\" (y/n)? "
read answer
case "$answer" in
[nN]) echo "Changed your mind, huh?"
exit $E_CHANGED_MIND
;;
*) echo "Blotting out file \"$file\".";;
esac
flength=$(ls -l "$file" | awk '{print $5}') # Field 5 is file length.
pass_count=1
chmod u+w "$file" # Allow overwriting/deleting the file.
echo
while [ "$pass_count" -le "$PASSES" ]
do
echo "Pass #$pass_count"
sync # Flush buffers.
dd if=/dev/urandom of=$file bs=$BLOCKSIZE count=$flength
# Fill with random bytes.
sync # Flush buffers again.
dd if=/dev/zero of=$file bs=$BLOCKSIZE count=$flength
# Fill with zeros.
sync # Flush buffers yet again.
let "pass_count += 1"
echo
done
rm -f $file # Finally, delete scrambled and shredded file.
sync # Flush buffers a final time.
echo "File \"$file\" blotted out and deleted."; echo
exit 0
# This is a fairly secure, if inefficient and slow method
#+ of thoroughly "shredding" a file.
# The "shred" command, part of the GNU "fileutils" package,
#+ does the same thing, although more efficiently.
# The file cannot not be "undeleted" or retrieved by normal methods.
# However . . .
#+ this simple method would *not* likely withstand
#+ sophisticated forensic analysis.
# This script may not play well with a journaled file system.
# Exercise (difficult): Fix it so it does.
# Tom Vier's "wipe" file-deletion package does a much more thorough job
#+ of file shredding than this simple script.
# http://www.ibiblio.org/pub/Linux/utils/file/wipe-2.0.0.tar.bz2
# For an in-depth analysis on the topic of file deletion and security,
#+ see Peter Gutmann's paper,
#+ "Secure Deletion of Data From Magnetic and Solid-State Memory".
# http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
>See also the <A
HREF="biblio.html#DDLINK"
>dd
thread</A
> entry in the <A
HREF="biblio.html#BIBLIOREF"
>bibliography</A
>.</P
></DD
><DT
><A
NAME="ODREF"
></A
><B
CLASS="COMMAND"
>od</B
></DT
><DD
><P
>The <B
CLASS="COMMAND"
>od</B
>, or <I
CLASS="FIRSTTERM"
>octal
dump</I
> filter converts input (or files) to octal
(base-8) or other bases. This is useful for viewing or
processing binary data files or otherwise unreadable system
<A
HREF="devref1.html#DEVFILEREF"
>device files</A
>, such as
<TT
CLASS="FILENAME"
>/dev/urandom</TT
>, and as a filter for
binary data.</P
><P
> <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p'
# Sample output: 1324725719, 3918166450, 2989231420, etc.
# From rnd.sh example script, by St<53>phane Chazelas</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>See also <A
HREF="randomvar.html#SEEDINGRANDOM"
>Example 9-16</A
> and <A
HREF="contributed-scripts.html#INSERTIONSORT"
>Example A-36</A
>.</P
></DD
><DT
><A
NAME="HEXDUMPREF"
></A
><B
CLASS="COMMAND"
>hexdump</B
></DT
><DD
><P
>Performs a hexadecimal, octal, decimal, or ASCII
dump of a binary file. This command is the rough equivalent
of <B
CLASS="COMMAND"
>od</B
>, above, but not nearly as
useful. May be used to view the contents of a binary file,
in combination with <A
HREF="extmisc.html#DDREF"
>dd</A
> and <A
HREF="filearchiv.html#LESSREF"
>less</A
>.</P
><P
> <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>dd if=/bin/ls | hexdump -C | less
# The -C option nicely formats the output in tabular form.</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DD
><DT
><A
NAME="OBJDUMPREF"
></A
><B
CLASS="COMMAND"
>objdump</B
></DT
><DD
><P
>Displays information about an object file or binary
executable in either hexadecimal form or as a disassembled
listing (with the <TT
CLASS="OPTION"
>-d</TT
> option).</P
><P
> <TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
><TT
CLASS="PROMPT"
>bash$ </TT
><TT
CLASS="USERINPUT"
><B
>objdump -d /bin/ls</B
></TT
>
<TT
CLASS="COMPUTEROUTPUT"
>/bin/ls: file format elf32-i386
Disassembly of section .init:
080490bc &#60;.init&#62;:
80490bc: 55 push %ebp
80490bd: 89 e5 mov %esp,%ebp
. . .</TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DD
><DT
><A
NAME="MCOOKIEREF"
></A
><B
CLASS="COMMAND"
>mcookie</B
></DT
><DD
><P
>This command generates a <SPAN
CLASS="QUOTE"
>"magic cookie,"</SPAN
> a
128-bit (32-character) pseudorandom hexadecimal number,
normally used as an authorization <SPAN
CLASS="QUOTE"
>"signature"</SPAN
>
by the X server. This also available for use in a script
as a <SPAN
CLASS="QUOTE"
>"quick 'n dirty"</SPAN
> random number.</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>random000=$(mcookie)</PRE
></FONT
></TD
></TR
></TABLE
></P
><P
>Of course, a script could use <A
HREF="filearchiv.html#MD5SUMREF"
>md5sum</A
> for the same purpose.</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
># Generate md5 checksum on the script itself.
random001=`md5sum $0 | awk '{print $1}'`
# Uses 'awk' to strip off the filename.</PRE
></FONT
></TD
></TR
></TABLE
></P
><P
>The <B
CLASS="COMMAND"
>mcookie</B
> command gives yet another way
to generate a <SPAN
CLASS="QUOTE"
>"unique"</SPAN
> filename.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="TEMPFILENAME"
></A
><P
><B
>Example 16-62. Filename generator</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# tempfile-name.sh: temp filename generator
BASE_STR=`mcookie` # 32-character magic cookie.
POS=11 # Arbitrary position in magic cookie string.
LEN=5 # Get $LEN consecutive characters.
prefix=temp # This is, after all, a "temp" file.
# For more "uniqueness," generate the
#+ filename prefix using the same method
#+ as the suffix, below.
suffix=${BASE_STR:POS:LEN}
# Extract a 5-character string,
#+ starting at position 11.
temp_filename=$prefix.$suffix
# Construct the filename.
echo "Temp filename = "$temp_filename""
# sh tempfile-name.sh
# Temp filename = temp.e19ea
# Compare this method of generating "unique" filenames
#+ with the 'date' method in ex51.sh.
exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DD
><DT
><A
NAME="UNITSREF"
></A
><B
CLASS="COMMAND"
>units</B
></DT
><DD
><P
>This utility converts between different <I
CLASS="FIRSTTERM"
>units
of measure</I
>. While normally invoked in interactive
mode, <B
CLASS="COMMAND"
>units</B
> may find use in a
script.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="UNITCONVERSION"
></A
><P
><B
>Example 16-63. Converting meters to miles</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# unit-conversion.sh
# Must have 'units' utility installed.
convert_units () # Takes as arguments the units to convert.
{
cf=$(units "$1" "$2" | sed --silent -e '1p' | awk '{print $2}')
# Strip off everything except the actual conversion factor.
echo "$cf"
}
Unit1=miles
Unit2=meters
cfactor=`convert_units $Unit1 $Unit2`
quantity=3.73
result=$(echo $quantity*$cfactor | bc)
echo "There are $result $Unit2 in $quantity $Unit1."
# What happens if you pass incompatible units,
#+ such as "acres" and "miles" to the function?
exit 0
# Exercise: Edit this script to accept command-line parameters,
# with appropriate error checking, of course.</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DD
><DT
><A
NAME="M4REF"
></A
><B
CLASS="COMMAND"
>m4</B
></DT
><DD
><P
>A hidden treasure, <B
CLASS="COMMAND"
>m4</B
> is a
powerful macro
<A
NAME="AEN14523"
HREF="#FTN.AEN14523"
><SPAN
CLASS="footnote"
>[6]</SPAN
></A
>
processing filter, virtually a complete language.
Although originally written as a pre-processor
for <I
CLASS="FIRSTTERM"
>RatFor</I
>, <B
CLASS="COMMAND"
>m4</B
>
turned out to be useful as a stand-alone utility. In
fact, <B
CLASS="COMMAND"
>m4</B
> combines some of the
functionality of <A
HREF="internal.html#EVALREF"
>eval</A
>,
<A
HREF="textproc.html#TRREF"
>tr</A
>, and <A
HREF="awk.html#AWKREF"
>awk</A
>, in addition to its extensive
macro expansion facilities.</P
><P
>The April, 2002 issue of <A
HREF="http://www.linuxjournal.com"
TARGET="_top"
><I
CLASS="CITETITLE"
>Linux Journal</I
></A
>
has a very nice article on <B
CLASS="COMMAND"
>m4</B
> and
its uses.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="M4"
></A
><P
><B
>Example 16-64. Using <I
CLASS="FIRSTTERM"
>m4</I
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# m4.sh: Using the m4 macro processor
# Strings
string=abcdA01
echo "len($string)" | m4 # 7
echo "substr($string,4)" | m4 # A01
echo "regexp($string,[0-1][0-1],\&#38;Z)" | m4 # 01Z
# Arithmetic
var=99
echo "incr($var)" | m4 # 100
echo "eval($var / 3)" | m4 # 33
exit</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DD
><DT
><A
NAME="XMESSAGEREF"
></A
><B
CLASS="COMMAND"
>xmessage</B
></DT
><DD
><P
>This X-based variant of
<A
HREF="internal.html#ECHOREF"
>echo</A
> pops up a message/query
window on the desktop.</P
><P
> <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>xmessage Left click to continue -button okay</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DD
><DT
><A
NAME="ZENITYREF"
></A
><B
CLASS="COMMAND"
>zenity</B
></DT
><DD
><P
>The
<A
HREF="http://freshmeat.net/projects/zenity"
TARGET="_top"
>zenity</A
>
utility is adept at displaying
<I
CLASS="FIRSTTERM"
>GTK+</I
> dialog <A
HREF="assortedtips.html#WIDGETREF"
>widgets</A
> and <A
HREF="assortedtips.html#ZENITYREF2"
>very suitable for scripting
purposes</A
>.</P
></DD
><DT
><A
NAME="DOEXECREF"
></A
><B
CLASS="COMMAND"
>doexec</B
></DT
><DD
><P
>The <B
CLASS="COMMAND"
>doexec</B
> command enables passing
an arbitrary list of arguments to a <I
CLASS="FIRSTTERM"
>binary
executable</I
>. In particular, passing
<TT
CLASS="PARAMETER"
><I
>argv[0]</I
></TT
> (which corresponds to <A
HREF="othertypesv.html#POSPARAMREF1"
>$0</A
> in a script) lets the
executable be invoked by various names, and it can then
carry out different sets of actions, according to the name
by which it was called. What this amounts to is roundabout
way of passing options to an executable.</P
><P
>For example, the <TT
CLASS="FILENAME"
>/usr/local/bin</TT
> directory might
contain a binary called <SPAN
CLASS="QUOTE"
>"aaa"</SPAN
>. Invoking
<B
CLASS="COMMAND"
>doexec /usr/local/bin/aaa list</B
>
would <EM
>list</EM
> all those files
in the current working directory beginning with an
<SPAN
CLASS="QUOTE"
>"a"</SPAN
>, while invoking (the same executable
with) <B
CLASS="COMMAND"
>doexec /usr/local/bin/aaa delete </B
>
would <EM
>delete</EM
> those files.</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="90%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>The various behaviors of the executable
must be defined within the code of the executable itself,
analogous to something like the following in a shell script:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>case `basename $0` in
"name1" ) do_something;;
"name2" ) do_something_else;;
"name3" ) do_yet_another_thing;;
* ) bail_out;;
esac</PRE
></FONT
></TD
></TR
></TABLE
></P
></TD
></TR
></TABLE
></DIV
></DD
><DT
><B
CLASS="COMMAND"
>dialog</B
></DT
><DD
><P
>The <A
HREF="assortedtips.html#DIALOGREF"
>dialog</A
> family of tools
provide a method of calling interactive
<SPAN
CLASS="QUOTE"
>"dialog"</SPAN
> boxes from a script. The more
elaborate variations of <B
CLASS="COMMAND"
>dialog</B
> --
<B
CLASS="COMMAND"
>gdialog</B
>, <B
CLASS="COMMAND"
>Xdialog</B
>,
and <B
CLASS="COMMAND"
>kdialog</B
> -- actually invoke X-Windows
<A
HREF="assortedtips.html#WIDGETREF"
>widgets</A
>.</P
></DD
><DT
><A
NAME="SOXREF"
></A
><B
CLASS="COMMAND"
>sox</B
></DT
><DD
><P
>The <B
CLASS="COMMAND"
>sox</B
>, or
<SPAN
CLASS="QUOTE"
>"<B
CLASS="COMMAND"
>so</B
>und
e<B
CLASS="COMMAND"
>x</B
>change"</SPAN
> command plays and
performs transformations on sound files. In fact,
the <TT
CLASS="FILENAME"
>/usr/bin/play</TT
> executable
(now deprecated) is nothing but a shell wrapper for
<I
CLASS="FIRSTTERM"
>sox</I
>.</P
><P
>For example, <B
CLASS="COMMAND"
>sox soundfile.wav
soundfile.au</B
> changes a WAV sound file into a
(Sun audio format) AU sound file.</P
><P
>Shell scripts are ideally suited for batch-processing
<B
CLASS="COMMAND"
>sox</B
> operations on
sound files. For examples, see the <A
HREF="http://osl.iu.edu/~tveldhui/radio/"
TARGET="_top"
> Linux Radio
Timeshift HOWTO</A
> and the <A
HREF="http://savannah.nongnu.org/projects/audiodo"
TARGET="_top"
>MP3do
Project</A
>.</P
></DD
></DL
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN14105"
HREF="extmisc.html#AEN14105"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>This is actually a script adapted from
the Debian Linux distribution.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN14214"
HREF="extmisc.html#AEN14214"
><SPAN
CLASS="footnote"
>[2]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>The <I
CLASS="FIRSTTERM"
>print queue</I
> is
the group of jobs <SPAN
CLASS="QUOTE"
>"waiting in line"</SPAN
> to be
printed.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN14218"
HREF="extmisc.html#AEN14218"
><SPAN
CLASS="footnote"
>[3]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>Large mechanical <I
CLASS="FIRSTTERM"
>line
printers</I
> printed a single
line of type at a time onto joined
sheets of <I
CLASS="FIRSTTERM"
>greenbar</I
>
paper, to the accompaniment of <A
HREF="http://www.columbia.edu/cu/computinghistory/1403.html"
TARGET="_top"
>a
great deal of noise</A
>. The hardcopy
thusly printed was referred to as a
<I
CLASS="FIRSTTERM"
>printout</I
>.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN14280"
HREF="extmisc.html#AEN14280"
><SPAN
CLASS="footnote"
>[4]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>For an excellent overview of this
topic, see Andy Vaught's article, <A
HREF="http://www2.linuxjournal.com/lj-issues/issue41/2156.html"
TARGET="_top"
>Introduction
to Named Pipes</A
>, in the September, 1997 issue of
<A
HREF="http://www.linuxjournal.com"
TARGET="_top"
><I
CLASS="CITETITLE"
>Linux
Journal</I
></A
>.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN14318"
HREF="extmisc.html#AEN14318"
><SPAN
CLASS="footnote"
>[5]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
><SPAN
CLASS="ACRONYM"
>EBCDIC</SPAN
> (pronounced
<SPAN
CLASS="QUOTE"
>"ebb-sid-ick"</SPAN
>) is an acronym for Extended
Binary Coded Decimal Interchange Code, an obsolete
IBM data format. A bizarre application of
the <TT
CLASS="OPTION"
>conv=ebcdic</TT
> option of
<B
CLASS="COMMAND"
>dd</B
> is as a quick 'n easy, but not
very secure text file encoder.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>cat $file | dd conv=swab,ebcdic &#62; $file_encrypted
# Encode (looks like gibberish).
# Might as well switch bytes (swab), too, for a little extra obscurity.
cat $file_encrypted | dd conv=swab,ascii &#62; $file_plaintext
# Decode.</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN14523"
HREF="extmisc.html#AEN14523"
><SPAN
CLASS="footnote"
>[6]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>A <I
CLASS="FIRSTTERM"
>macro</I
> is a
symbolic constant that expands into a command string
or a set of operations on parameters. Simply put,
it's a shortcut or abbreviation.</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="mathc.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="system.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Math Commands</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="external.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>System and Administrative Commands</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>