This commit is contained in:
gferg 2003-05-12 14:45:05 +00:00
parent 738864a37c
commit 1023b2f15b
10 changed files with 772 additions and 200 deletions

View File

@ -3,6 +3,80 @@ RELEASE HISTORY
Change log
Version 1.8 [Cleanups & revisions]
Working toward 'BREADFRUIT' release
1) Revised "self-document.sh" to remove unnecessary 'cat.'
2) In "cvt.sh" example, quoted target file name and added exercise.
3) Updated Jordi Sanfeliu's e-mail address in "Credits" chapter and in
"tree.sh" example script.
4) In "blot-out.sh" script, updated the Peter Gutmann URL.
5) In "Miscellaneous" subsection of "System and Administrative Commands"
chapter"
Added "watch" command.
6) In the introduction, in reason not to use shell scripts,
Removed misleading reference to Open Source (thank you, Peter Lietz, for
pointing this out).
7) In "Quoting" chapter:
Added footnote about problem double quoting "!" and "\!".
(Thanks, Wayne Pollock.)
8) In "Internal Commands" chapter:
Added caution about 'cd //' problem. (Thanks, Wayne Pollock.)
Added short example of "$!" usage. (Thanks, Jacques Lederer.)
9) In "Arrays" chapter:
Replaced "empty-array.sh" with an extended version.
Added note that Bash treats variables as arrays, even if not declared as
such.
Added example of nested arrays.
Added example of copying and concatenating arrays.
(All the above thanks to Michael Zick.)
10) In "Tests" chapter:
Fixed up "Tests Constructs" section link (finally!).
11) In "Command Substitution" chapter:
Added mention of $(<$file) construct.
12) In "Functions" chapter:
Added material to nested functions in-line examples.
13) In the "Portability Issues" section of the "Miscellany" chapter:
Added short list of Bash-specific features.
14) In "File and Archiving Commands" section of "External Commands" Chapter:
Added "dos2unix" utility.
15) In "Gotchas" chapter:
Added short in-line example of using an uninitialized variable.
Added in-line example showing DOS-formatted script failing to run.
16) In "Contributed Scripts" appendix:
Added Michael Zick's "directory-info.sh" script.
17) In "Bibliography" section:
Updated "The UNIX CD Bookshelf" reference.
Added Eric Pement's sed resources page.
Removed outdated "Sed F.A.Q." reference.
Updated Frisch entry.
Updated Shelldorado and Giles Orr entries.
18) Updated sample .bashrc file (Appendix G).
19) A few minor error corrections and clean ups at various places in the
text.
Version 1.7 (minor update)
'COCONUT' release
01/05/03

View File

@ -17,6 +17,8 @@ read-r.sh
rnd.sh
rot13.sh
here-function.sh
directory-info.sh (lines 273 and 353)
bashrc (comments on lines 596 and 618)
have the "&lt;" and "&gt;" in place of angle brackets (< and >), or &amp; in
place of the ampersand (&). This is necessary for the Docbook SGML

View File

@ -268,6 +268,8 @@ Uncomment line below to generate index.
<!ENTITY brokenlink SYSTEM "broken-link.sh">
<!ENTITY continuenex SYSTEM "continue-n.example">
<!ENTITY pickcard SYSTEM "pick-card.sh">
<!ENTITY copyarray SYSTEM "CopyArray.sh">
<!ENTITY directoryinfo SYSTEM "directory-info.sh">
<!ENTITY evalex SYSTEM "eval.example">
<!ENTITY namesdata SYSTEM "names.data">
<!ENTITY gen0data SYSTEM "gen0">
@ -277,20 +279,20 @@ Uncomment line below to generate index.
<book>
<bookinfo>
<title>Advanced Bash-Scripting Guide</title>
<subtitle>An in-depth exploration of the gentle art of shell scripting</subtitle>
<subtitle>An in-depth exploration of the art of shell scripting</subtitle>
<author>
<firstname>Mendel</firstname>
<surname>Cooper</surname>
<affiliation>
<orgname>Brindle-Phlogiston Associates</orgname>
<orgname></orgname>
<address><email>thegrendel@theriver.com</email></address>
</affiliation>
</author>
<releaseinfo>1.7</releaseinfo>
<pubdate>05 January 2003</pubdate>
<releaseinfo>1.8</releaseinfo>
<pubdate>10 May 2003</pubdate>
<revhistory>
@ -395,6 +397,14 @@ Uncomment line below to generate index.
more script.</revremark>
</revision>
<revision>
<revnumber>1.8</revnumber>
<date>10 May 2003</date>
<authorinitials>mc</authorinitials>
<revremark>'BREADFRUIT' release: a number of bugfixes, more scripts
and material.</revremark>
</revision>
</revhistory>
@ -402,7 +412,7 @@ Uncomment line below to generate index.
<para>This tutorial assumes no previous knowledge of
scripting or programming, but progresses rapidly toward an
intermediate/advanced level of instruction <emphasis>...all
intermediate/advanced level of instruction <emphasis>. . . all
the while sneaking in little snippets of UNIX wisdom and
lore</emphasis>. It serves as a textbook, a manual for
self-study, and a reference and source of knowledge on shell
@ -415,7 +425,7 @@ Uncomment line below to generate index.
linkend="bzipref">bzip2-ed</link> <quote>tarball</quote>
including both the SGML source and
rendered HTML, may be downloaded from <ulink
url="http://personal.riverusers.com/~thegrendel/abs-guide-1.7.tar.bz2">
url="http://personal.riverusers.com/~thegrendel/abs-guide-1.8.tar.bz2">
the author's home site</ulink>. See the <ulink
url="http://personal.riverusers.com/~thegrendel/Change.log">change
log</ulink> for a revision history.</para>
@ -456,7 +466,7 @@ Uncomment line below to generate index.
<para>A working knowledge of shell scripting is essential to anyone
wishing to become reasonably adept at system administration,
wishing to become reasonably proficient at system administration,
even if they do not anticipate ever having to actually write a
script. Consider that as a Linux machine boots up, it executes the
shell scripts in <filename class="directory">/etc/rc.d</filename>
@ -510,7 +520,7 @@ Uncomment line below to generate index.
<para>cross-platform portability required (use C instead)</para>
</listitem> <listitem>
<para>complex applications, where structured programming is
a necessity (need typechecking of variables, function
a necessity (need type-checking of variables, function
prototypes, etc.)</para>
</listitem> <listitem>
<para>mission-critical applications upon which you are betting the
@ -539,8 +549,9 @@ Uncomment line below to generate index.
</listitem> <listitem>
<para>need to use libraries or interface with legacy code</para>
</listitem> <listitem>
<para>proprietary, closed-source applications (shell scripts are
necessarily Open Source)</para>
<para>proprietary, closed-source applications (shell scripts put the
source code right out in the open for all the world to see)</para>
</listitem>
</itemizedlist></para>
@ -562,19 +573,19 @@ Uncomment line below to generate index.
and even a few from the updated <emphasis>ksh93</emphasis>
have been merged into Bash.</para></footnote>
and the C Shell and its variants. (Note that C Shell programming
and the C Shell and its variants. (Note that C Shell programming
is not recommended due to certain inherent problems, as pointed out
in an October, 1993 <ulink
url="http://www.etext.org/Quartz/computer/unix/csh.harmful.gz">Usenet
post</ulink> by Tom Christiansen).
post</ulink> by Tom Christiansen.)
</para>
<para>What follows is a tutorial on shell scripting. It relies
heavily on examples to illustrate various features of the shell.
As far as possible, the example scripts have been tested,
and some of them may even be useful in real life. The
reader should use the actual examples in the source archive
(<filename>something-or-other.sh</filename>),
The example scripts work -- they've been tested -- and some
of them are even useful in real life. The reader can play with
the actual working code of the examples in the source archive
(<filename>scriptname.sh</filename>),
<footnote><para>By convention, user-written shell scripts that are
Bourne shell compliant generally take a name with a
@ -585,13 +596,13 @@ Uncomment line below to generate index.
give them execute permission (<userinput>chmod u+rx
scriptname</userinput>), then run them to see what happens.
Should the source archive not be available, then cut-and-paste from
the HTML, pdf, or text rendered versions. Be aware that some of
the HTML, pdf, or text rendered versions. Be aware that some of
the scripts below introduce features before they are explained,
and this may require the reader to temporarily skip ahead for
enlightenment.</para>
<para>Unless otherwise noted, the book author wrote the example
scripts that follow.</para>
<para>Unless otherwise noted, the author of this book wrote the
example scripts that follow.</para>
</chapter> <!-- Why Shell Programming? -->
@ -906,9 +917,9 @@ fi</programlisting>
<note><para>Of course, an escaped <token>#</token> in an
<command>echo</command> statement does
<emphasis>not</emphasis> begin a comment. Likewise, a
<token>#</token> appears in <link linkend="psub2">certain
parameter substitution constructs</link> and in <link
linkend="numconstants">numerical constant expressions</link>.
<token>#</token> appears in <link linkend="psub2">certain parameter
substitution constructs</link> and in <link linkend="numconstants">
numerical constant expressions</link>.
<programlisting>echo "The # here does not begin a comment."
echo 'The # here does not begin a comment.'
@ -2884,6 +2895,7 @@ arch=$(uname -m)</programlisting></para>
<sect1 id="untyped">
<title>Bash Variables Are Untyped</title>
<para><anchor id="bvuntyped"></para>
<para>Unlike many other programming languages, Bash does not segregate
its variables by <quote>type</quote>. Essentially, Bash
variables are character strings, but, depending on context, Bash
@ -2946,10 +2958,11 @@ arch=$(uname -m)</programlisting></para>
any other process.</para>
<para>Every time a shell starts, it creates shell variables that
correspond to its own environmental variables. Updating or
adding new shell variables causes the shell to update its
environment, and all the shell's child processes (the commands
it executes) inherit this environment.</para>
correspond to its own environmental variables. Updating
or adding new environmental variables causes the shell
to update its environment, and all the shell's child
processes (the commands it executes) inherit this
environment.</para>
</note>
@ -3185,8 +3198,45 @@ fi
enclose it in double quotes (<token>" "</token>). This
preserves all special characters within the variable name,
except <token>$</token>, <token>`</token> (backquote),
and <token>\</token> (escape). Keeping <token>$</token>
as a special character permits referencing a quoted variable
and <token>\</token> (escape).
<footnote>
<para>Encapsulating <quote>!</quote> within double
quotes gives an error when used <emphasis>from the command
line</emphasis>. Apparently this is interpreted as a <link
linkend="histcommands">history command</link>. Within a script,
though, this problem does not occur.</para>
<para>Of more concern is the inconsistent behavior of
<quote>\</quote> within double quotes.
<screen>
<prompt>bash$ </prompt><userinput>echo hello\!</userinput>
<computeroutput>hello!</computeroutput>
<prompt>bash$ </prompt><userinput>echo "hello\!"</userinput>
<computeroutput>hello\!</computeroutput>
<prompt>bash$ </prompt><userinput>echo -e x\ty</userinput>
<computeroutput>xty</computeroutput>
<prompt>bash$ </prompt><userinput>echo -e "x\ty"</userinput>
<computeroutput>x y</computeroutput>
</screen>
(Thank you, Wayne Pollock, for pointing this out.)
</para>
</footnote>
Keeping <token>$</token> as a special character within
double quotes permits referencing a quoted variable
(<replaceable>"$variable"</replaceable>), that is, replacing the
variable with its value (see <xref linkend="ex9">, above).</para>
@ -3750,7 +3800,9 @@ echo "exit status of \"! true\" = $?" # 1
<command>if/then</command> construct.</para>
<sect1 id="testconstructs">
<title><anchor id="testconstructs1">Test Constructs</title>
<title>Test Constructs</title>
<para><anchor id="testconstructs1"></para>
<itemizedlist id="testingref">
@ -3993,8 +4045,8 @@ fi</programlisting>
</indexterm>
<para><anchor id="dblbrackets">The <token>[[ ]]</token> construct
is the shell equivalent of <token>[ ]</token>. This is the
<emphasis>extended test command</emphasis>, adopted from
is the more versatile Bash version of <token>[ ]</token>. This
is the <emphasis>extended test command</emphasis>, adopted from
<emphasis>ksh88</emphasis>.</para>
<note><para>No filename expansion or word splitting takes place
@ -6468,7 +6520,28 @@ echo "$@" # 3 4 5
<secondary>last job background</secondary>
</indexterm>
<listitem>
<para>PID (process id) of last job run in background</para>
<para>
<programlisting>LOG=$0.log
COMMAND1="sleep 100"
echo "Logging PIDs background commands for script: $0" >> "$LOG"
# So they can be monitored, and killed as necessary.
echo >> "$LOG"
# Logging commands.
echo -n "PID of \"$COMMAND1\": " >> "$LOG"
${COMMAND1} &
echo $! >> "$LOG"
# PID of "sleep 100": 1506
# Thank you, Jacques Lederer, for suggesting this.</programlisting>
</para>
</listitem>
</varlistentry>
@ -8791,6 +8864,19 @@ done</programlisting></para>
linkend="oldpwd">$OLDPWD</link>, the previous working
directory.</para>
<para><anchor id="doubleslashref"></para>
<caution><para>The <command>cd</command> command does not function
as expected when presented with two forward slashes.
<screen>
<prompt>bash$ </prompt><userinput>cd //</userinput>
<prompt>bash$ </prompt><userinput>pwd</userinput>
<computeroutput>//</computeroutput>
</screen>
The output should, of course, be <computeroutput>/</computeroutput>.
This is a problem both from the command line and in a script.</para></caution>
</listitem>
</varlistentry>
@ -10914,11 +11000,17 @@ find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \
<programlisting>sleep 3
# Pauses 3 seconds.</programlisting>
</para>
<note><para>The <command>sleep</command> command defaults to
seconds, but minute, hours, or days may also be specified.
<programlisting>sleep 3 h
# Pauses 3 hours!</programlisting>
</para></note>
<note><para>The <link linkend="watchref">watch</link> command may
be a better choice than <command>sleep</command> for running
commands at timed intervals.</para></note>
</listitem>
</varlistentry>
@ -13142,6 +13234,9 @@ gzip -cd patchXX.gz | patch -p0
<programlisting>&fileintegrity;</programlisting>
</example>
<para>See also <xref linkend="directoryinfo"> for a creative use of
the <command>md5sum</command> command.</para>
</listitem>
</varlistentry>
@ -13348,6 +13443,23 @@ echo "tempfile name = $tempfile"
</listitem>
</varlistentry>
<varlistentry>
<term><command>dos2unix</command></term>
<indexterm>
<primary>dos2unix</primary>
</indexterm>
<indexterm>
<primary>command</primary>
<secondary>file converter</secondary>
</indexterm>
<listitem>
<para>This utility, written by Benjamin Lin and collaborators,
converts DOS-formatted text files (lines terminated by
CR-LF) to UNIX format (lines terminated by LF only),
and vice-versa.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>ptx</command></term>
<indexterm>
@ -17609,6 +17721,24 @@ print "even when I don't know where to find Perl.\n";
</listitem>
</varlistentry>
<varlistentry>
<term><anchor id="watchref"><command>watch</command></term>
<indexterm>
<primary>watch</primary>
</indexterm>
<indexterm>
<primary>command</primary>
<secondary>periodic</secondary>
</indexterm>
<listitem>
<para>Run a command repeatedly, at specified time intervals.</para>
<para>The default is two-second intervals, but this may be changed
with the <option>-n</option> option.</para>
<para><programlisting>watch -n 5 tail /var/log/messages
# Shows tail end of system log, /var/log/messages, every five seconds.</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>strip</command></term>
<indexterm>
@ -17849,7 +17979,11 @@ echo "$dir_listing" # quoted
<programlisting>variable1=`&lt;file1` # Set "variable1" to contents of "file1".
variable2=`cat file2` # Set "variable2" to contents of "file2".
# Be aware that the variables may contain embedded whitespace,
# Note 1:
# Removes newlines.
#
# Note 2:
# The variables may contain embedded whitespace,
#+ or even (horrors), control characters.</programlisting>
</para>
@ -17951,8 +18085,11 @@ echo $greeting</programlisting>
<note><para>The <command>$(COMMAND)</command> form has
superseded backticks for command substitution.
<programlisting>output=$(sed -n /"$1"/p $file)
# From "grp.sh" example.</programlisting></para></note>
<programlisting>output=$(sed -n /"$1"/p $file) # From "grp.sh" example.
# Setting a variable to the contents of a text file.
File_contents1=$(cat $file1)
File_contents2=$(&lt;$file2) # Bash permits this also.</programlisting></para></note>
@ -18003,7 +18140,7 @@ echo $greeting</programlisting>
</indexterm> <indexterm>
<primary>arithmetic</primary> <secondary>expansion</secondary>
</indexterm> <listitem>
<para><programlisting>z=`expr $z + 3` # 'expr' does the expansion.</programlisting></para>
<para><programlisting>z=`expr $z + 3` # The 'expr' command performs the expansion.</programlisting></para>
</listitem>
</varlistentry>
@ -18026,12 +18163,13 @@ echo $greeting</programlisting>
convenient <command>let</command> construction.
<programlisting>z=$(($z+3))
# $((EXPRESSION)) is arithmetic expansion. # Not to be confused with
# command substitution.
# $((EXPRESSION)) is arithmetic expansion. # Not to be confused with
#+ command substitution.
let z=z+3
let "z += 3" #If quotes, then spaces and special operators allowed.
# 'let' is actually arithmetic evaluation, rather than expansion.</programlisting>
let "z += 3" # Quotes permit the use of spaces and special operators.
# The 'let' operator actually performs arithmetic evaluation,
#+ rather than expansion.</programlisting>
All the above are equivalent. You may use whichever one
<quote>rings your chimes</quote>.
@ -19767,9 +19905,12 @@ route -n |
<para>The function definition must precede the first call to
it. There is no method of <quote>declaring</quote> the function,
as, for example, in C.
<programlisting># f1
<programlisting>f1
# Will give an error message, since function "f1" not yet defined.
declare -f f1 # This doesn't help either.
f1 # Still an error message.
# However...
@ -19784,11 +19925,11 @@ f2 ()
echo "Function \"f2\"."
}
f1 # Function "f2" is not actually called until this point,
# although it is referenced before its definition.
# This is permissable.
f1 # Function "f2" is not actually called until this point,
#+ although it is referenced before its definition.
# This is permissable.
# Thanks, S.C.</programlisting>
# Thanks, S.C.</programlisting>
</para>
<para>It is even possible to nest a function within another function,
@ -19803,14 +19944,16 @@ f1 # Function "f2" is not actually called until this point,
}
# f2
# Gives an error message.
f2 # Gives an error message.
# Even a preceding "declare -f f2" wouldn't help.
f1 # Does nothing, since calling "f1" does not automatically call "f2".
f2 # Now, it's all right to call "f2",
# since its definition has been made visible by calling "f1".
echo
# Thanks, S.C.</programlisting>
f1 # Does nothing, since calling "f1" does not automatically call "f2".
f2 # Now, it's all right to call "f2",
#+ since its definition has been made visible by calling "f1".
# Thanks, S.C.</programlisting>
</para>
<para>Function declarations can appear in unlikely places, even where a
@ -20419,6 +20562,25 @@ false && ( true || echo false ) # (nothing echoed)
<programlisting>&ex66;</programlisting>
</example>
<note><para>Bash permits array operations on variables, even if
the variables are not explicitly declared as arrays.
<programlisting>string=abcABC123ABCabc
echo ${string[@]} # abcABC123ABCabc
echo ${string[*]} # abcABC123ABCabc
echo ${string[0]} # abcABC123ABCabc
echo ${string[1]} # No output!
# Why?
echo ${#string[@]} # 1
# One element in the array.
# The string itself.
# Thank you, Michael Zick, for pointing this out.</programlisting>
Once again this demonstrates that <link linkend="bvuntyped">Bash
variables are untyped</link>.
</para></note>
<example id="poem">
<title>Formatting a poem</title>
<programlisting>&poem;</programlisting>
@ -20522,7 +20684,15 @@ element_count=${#array1[*]}
echo $element_count # 8</programlisting>
</para>
</tip>
<para>Clever scripting makes it possible to add array operations.</para>
<example id="copyarray">
<title>Copying and concatenating arrays</title>
<programlisting>&copyarray;</programlisting>
</example>
<para>--</para>
<para>Arrays permit deploying old familiar algorithms as shell scripts.
Whether this is necessarily a good idea is left to the reader to
@ -20536,6 +20706,28 @@ echo $element_count # 8</programlisting>
<para>--</para>
<para>Is it possible to nest arrays within arrays?</para>
<para><programlisting>#!/bin/bash
# Nested array.
# Michael Zick provided this example.
AnArray=( $(ls --inode --ignore-backups --almost-all \
--directory --full-time --color=none --time=status \
--sort=time -l ${PWD} ) ) # Commands and options.
# Spaces are significant . . . and don't quote anything in the above.
SubArray=( ${AnArray[@]:11:1} ${AnArray[@]:6:5} )
# Array has two elements, each of which is in turn an array.
echo "Current directory and date of last status change:"
echo "${SubArray[@]}"
exit 0</programlisting></para>
<para>--</para>
<para>Arrays enable implementing a shell script version of the <emphasis>Sieve of
Eratosthenes</emphasis>. Of course, a resource-intensive application of this
nature should really be written in a compiled language, such as C. It
@ -21296,6 +21488,7 @@ trap 'echo "Control-C disabled."' 2
</programlisting></para>
<para><anchor id="invocationoptionsref"></para>
<para>It is also possible to enable script options from the command
line. Some options that will not work with
<command>set</command> are available this way. Among these
@ -21471,9 +21664,9 @@ do_something do_something
<para><anchor id="wsbad">Using <link
linkend="whitespaceref">whitespace</link> inappropriately
(in contrast to other programming languages, Bash can be quite
finicky about whitespace).
linkend="whitespaceref">whitespace</link> inappropriately.
In contrast to other programming languages, Bash can be quite
finicky about whitespace.
<programlisting>var1 = 23 # 'var1=23' is correct.
# On line above, Bash attempts to execute command "var1"
@ -21486,10 +21679,18 @@ if [ $a -le 5] # if [ $a -le 5 ] is correct.
# [[ $a -le 5 ]] also works.</programlisting>
</para>
<para>Assuming uninitialized variables (variables before a value is
<para>
Assuming uninitialized variables (variables before a value is
assigned to them) are <quote>zeroed out</quote>. An
uninitialized variable has a value of <quote>null</quote>,
<emphasis>not</emphasis> zero.</para>
<emphasis>not</emphasis> zero.
<programlisting>#!/bin/bash
echo "uninitialized_var = $uninitialized_var"
# uninitialized_var =</programlisting>
</para>
<para>Mixing up <emphasis>=</emphasis> and <emphasis>-eq</emphasis> in
a test. Remember, <emphasis>=</emphasis> is for comparing literal
@ -21593,11 +21794,27 @@ fi
<command>sh</command> to <command>bash</command>, but this does
not necessarily hold true for a generic UNIX machine.</para>
<para>A script with DOS-type newlines (<replaceable>\r\n</replaceable>)
<para>
A script with DOS-type newlines (<replaceable>\r\n</replaceable>)
will fail to execute, since <userinput>#!/bin/bash\r\n</userinput>
is not recognized, <emphasis>not</emphasis> the same as the
expected <userinput>#!/bin/bash\n</userinput>. The fix is to
convert the script to UNIX-style newlines.</para>
convert the script to UNIX-style newlines.
<programlisting>#!/bin/bash
echo "Here"
unix2dos $0 # Script changes itself to DOS format.
chmod 755 $0 # Change back to execute permission.
# The 'unix2dos' command removes execute permission.
./$0 # Script tries to run itself again.
# But it won't work as a DOS file.
echo "There"
exit 0</programlisting>
</para>
<para>A shell script headed by <userinput>#!/bin/sh</userinput>
may not run in full Bash-compatibility mode. Some Bash-specific
@ -21654,6 +21871,9 @@ exit 0</programlisting>
undesirable behavior as far as CGI is concerned. Moreover, it is
difficult to <quote>cracker-proof</quote> shell scripts.</para>
<para>Bash does not handle the <link linkend="doubleslashref">double slash
(<token>//</token>) string</link> correctly.</para>
<para>Bash scripts written for Linux or BSD systems may need
fixups to run on a commercial UNIX machine. Such scripts
often employ GNU commands and filters which have greater
@ -22796,12 +23016,46 @@ fi</programlisting>
features to the latest versions of Bash.</para>
<para>On a commercial UNIX machine, scripts using GNU-specific
features of standard commands may not work. This has become
less of a problem in the last few years, as the GNU utilities
have pretty much displaced their proprietary counterparts even
on <quote>big-iron</quote> UNIX. Caldera's recent release of
the source to many of the original UNIX utilities will only
accelerate the trend.</para>
features of standard commands may not work. This has become less
of a problem in the last few years, as the GNU utilities have
pretty much displaced their proprietary counterparts even on
<quote>big-iron</quote> UNIX. Caldera's release of the source
to many of the original UNIX utilities will only accelerate
the trend.</para>
<para>Bash has certain features that the traditional Bourne shell
lacks. Among these are:
<itemizedlist>
<listitem>
<para>Certain extended <link
linkend="invocationoptionsref">invocation options</link></para>
</listitem>
<listitem>
<para><link linkend="commandsubref">Command substitution</link> using
<command>$( )</command> notation</para>
</listitem>
<listitem>
<para>Certain <link linkend="stringmanip">string manipulation</link>
operations</para>
</listitem>
<listitem>
<para><link linkend="processsubref">Process substitution</link></para>
</listitem>
<listitem>
<para>Bash-specific <link linkend="builtinref">builtins</link></para>
</listitem>
</itemizedlist>
</para>
<para>See the <ulink url="ftp://ftp.cwru.edu/pub/bash/FAQ">Bash
F.A.Q.</ulink> for a complete listing.</para>
</sect1> <!-- Portability Issues -->
@ -23035,7 +23289,7 @@ fi</programlisting>
an instructive example script.</para>
<para>Many thanks to <ulink
url="mailto:mikaku@arrakis.es">Jordi Sanfeliu</ulink>
url="mailto:mikaku@fiwix.org">Jordi Sanfeliu</ulink>
for giving permission to use his fine tree script (<xref
linkend="tree">).</para>
@ -23075,6 +23329,10 @@ fi</programlisting>
linkend="cutref">cut</link> and <link
linkend="pidofref">pidof</link>.</para>
<para>Michael Zick extended the <link linkend="emptyarray">empty
array</link> example to demonstrate some surprising array
properties. He also provided other examples of this.</para>
<para>Marc-Jano Knopp sent corrections on DOS batch files.</para>
<para>Hyun Jin Cha found several typos in the document in the
@ -23162,18 +23420,18 @@ fi</programlisting>
<author><firstname>Aeleen</firstname><surname>Frisch</surname></author>
</authorgroup>
<title>Essential System Administration</title>
<edition>2nd edition</edition>
<edition>3rd edition</edition>
<publisher>
<publishername>O'Reilly and Associates</publishername>
</publisher>
<copyright>
<year>1995</year>
<year>2002</year>
</copyright>
<isbn>1-56592-127-5</isbn>
<isbn>0-596-00343-9</isbn>
<abstract><para>This excellent sys admin manual has a decent introduction to shell
scripting for sys administrators and does a nice job of explaining the
startup and initialization scripts. The book is long overdue for a third
edition (are you listening, Tim O'Reilly?).</para>
startup and initialization scripts. The long overdue third edition of this
classic has finally been released.</para>
<para>*</para>
</abstract>
</biblioentry>
@ -23459,21 +23717,20 @@ fi</programlisting>
<biblioentry>
<title>The UNIX CD Bookshelf</title>
<edition>2nd edition</edition>
<edition>3rd edition</edition>
<publisher>
<publishername>O'Reilly and Associates</publishername>
</publisher>
<copyright>
<year>2000</year>
<year>2003</year>
</copyright>
<isbn>1-56592-815-6</isbn>
<abstract><para>An array of six UNIX books on CD ROM, including
<isbn>0-596-00392-7</isbn>
<abstract><para>An array of seven UNIX books on CD ROM, including
<emphasis>UNIX Power Tools</emphasis>, <emphasis>Sed
and Awk</emphasis>, and <emphasis>Learning the Korn
Shell</emphasis>. A complete set of all the UNIX references
and tutorials you would ever need at about $70. Buy this one,
and tutorials you would ever need at about $130. Buy this one,
even if it means going into debt and not paying the rent.</para>
<para>Unfortunately, out of print at present.</para>
<para>*</para>
</abstract>
</biblioentry>
@ -23545,8 +23802,7 @@ fi</programlisting>
<biblioentry>
<abstract>
<para>Example shell scripts at <ulink
url="http://www.oase-shareware.org/shell/scripts">SHELLdorado
</ulink>.</para>
url="http://www.shelldorado.com">SHELLdorado </ulink>.</para>
</abstract>
</biblioentry>
@ -23577,19 +23833,11 @@ fi</programlisting>
<biblioentry>
<abstract>
<para>Giles Orr's <ulink
url="http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO.html">Bash-Prompt
url="http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/">Bash-Prompt
HOWTO</ulink>.</para>
</abstract>
</biblioentry>
<biblioentry>
<abstract>
<para>The <ulink
url="http://www.dbnet.ece.ntua.gr/~george/howto/sed/">sed F.A.Q. /
Do It With Sed</ulink>.</para>
</abstract>
</biblioentry>
<biblioentry>
<abstract>
<para>Very nice <command>sed</command>,
@ -23599,6 +23847,14 @@ fi</programlisting>
</abstract>
</biblioentry>
<biblioentry>
<abstract>
<para>Eric Pement's
<ulink url="http://www.student.northpark.edu/pemente/sed/">sed resources page</ulink>.</para>
</abstract>
</biblioentry>
<biblioentry>
<abstract>
<para>The GNU <command>gawk</command> <ulink
@ -23839,6 +24095,16 @@ fi</programlisting>
<programlisting>&string;</programlisting>
</example>
<para>Michael Zick's complex array example uses the <link
linkend="md5sumref">md5sum</link> check sum command to encode directory
information.</para>
<example id="directoryinfo">
<title>Directory information</title>
<programlisting>&directoryinfo;</programlisting>
</example>
<para>Stephane Chazelas demonstrates object-oriented programming in a
Bash script.</para>

View File

@ -1,19 +1,26 @@
#===============================================================
#
# PERSONAL $HOME/.bashrc FILE for bash-2.05 (or later)
# PERSONAL $HOME/.bashrc FILE for bash-2.05a (or later)
#
# Last modified: Tue Apr 15 20:32:34 CEST 2003
#
# This file is read (normally) by interactive shells only.
# Here is the place to define your aliases, functions and
# other interactive features like your prompt.
#
# This file was designed (originally) for Solaris.
# This file was designed (originally) for Solaris but based
# on Redhat's default .bashrc file
# --> Modified for Linux.
# The majority of the code you'll find here is based on code found
# on Usenet (or internet).
# This bashrc file is a bit overcrowded - remember it is just
# just an example. Tailor it to your needs
# just an example. Tailor it to your needs
#
#
#===============================================================
# --> Comments added by HOWTO author.
# --> And then edited again by ER :-)
#-----------------------------------
# Source global definitions (if any)
@ -25,38 +32,69 @@ fi
#-------------------------------------------------------------
# Automatic setting of $DISPLAY (if not set already)
# This works for linux and solaris - your mileage may vary....
# This works for linux - your mileage may vary....
# The problem is that different types of terminals give
# different answers to 'who am i'......
# I have not found a 'universal' method yet
#-------------------------------------------------------------
function get_xserver ()
{
case $TERM in
xterm )
XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )
XSERVER=${XSERVER%%:*}
;;
aterm | rxvt)
# find some code that works here.....
;;
esac
}
if [ -z ${DISPLAY:=""} ]; then
DISPLAY=$(who am i)
DISPLAY=${DISPLAY%%\!*}
if [ -n "$DISPLAY" ]; then
export DISPLAY=$DISPLAY:0.0
else
export DISPLAY=":0.0" # fallback
get_xserver
if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || ${XSERVER} == "unix" ]]; then
DISPLAY=":0.0" # Display on local host
else
DISPLAY=${XSERVER}:0.0 # Display on remote host
fi
fi
export DISPLAY
#---------------
# Some settings
#---------------
ulimit -S -c 0 # Don't want any coredumps
set -o notify
set -o noclobber
set -o ignoreeof
set -o nounset
#set -o xtrace # useful for debuging
# Enable options:
shopt -s cdspell
shopt -s cdable_vars
shopt -s checkhash
shopt -s checkwinsize
shopt -s mailwarn
shopt -s sourcepath
shopt -s no_empty_cmd_completion
shopt -s histappend histreedit
shopt -s extglob # useful for programmable completion
shopt -s no_empty_cmd_completion # bash>=2.04 only
shopt -s cmdhist
shopt -s histappend histreedit histverify
shopt -s extglob # necessary for programmable completion
# Disable options:
shopt -u mailwarn
unset MAILCHECK # I don't want my shell to warn me of incoming mail
export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n'
export HISTIGNORE="&:bg:fg:ll:h"
export HOSTFILE=$HOME/.hosts # Put a list of remote hosts in ~/.hosts
#-----------------------
# Greeting, motd etc...
@ -75,26 +113,37 @@ NC='\e[0m' # No Color
# Looks best on a black background.....
echo -e "${CYAN}This is BASH ${RED}${BASH_VERSION%.*}${CYAN} - DISPLAY on ${RED}$DISPLAY${NC}\n"
date
if [ -x /usr/games/fortune ]; then
if [ -x /usr/games/fortune ]; then
/usr/games/fortune -s # makes our day a bit more fun.... :-)
fi
function _exit() # function to run upon exit of shell
function _exit() # function to run upon exit of shell
{
echo -e "${RED}Hasta la vista, baby${NC}"
}
trap _exit 0
trap _exit EXIT
#---------------
# Shell prompt
# Shell Prompt
#---------------
if [[ "${DISPLAY#$HOST}" != ":0.0" && "${DISPLAY}" != ":0" ]]; then
HILIT=${red} # remote machine: prompt will be partly red
else
HILIT=${cyan} # local machine: prompt will be partly cyan
fi
# --> Replace instances of \W with \w in prompt functions below
#+ --> to get display of full path name.
function fastprompt()
{
unset PROMPT_COMMAND
case $TERM in
*term | rxvt )
PS1="[\h] \W > \[\033]0;[\u@\h] \w\007\]" ;;
PS1="${HILIT}[\h]$NC \W > \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
linux )
PS1="${HILIT}[\h]$NC \W > " ;;
*)
PS1="[\h] \W > " ;;
esac
@ -105,17 +154,16 @@ function powerprompt()
_powerprompt()
{
LOAD=$(uptime|sed -e "s/.*: \([^,]*\).*/\1/" -e "s/ //g")
TIME=$(date +%H:%M)
}
PROMPT_COMMAND=_powerprompt
case $TERM in
*term | rxvt )
PS1="${cyan}[\$TIME \$LOAD]$NC\n[\h \#] \W > \[\033]0;[\u@\h] \w\007\]" ;;
PS1="${HILIT}[\A \$LOAD]$NC\n[\h \#] \W > \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
linux )
PS1="${cyan}[\$TIME - \$LOAD]$NC\n[\h \#] \w > " ;;
PS1="${HILIT}[\A - \$LOAD]$NC\n[\h \#] \w > " ;;
* )
PS1="[\$TIME - \$LOAD]\n[\h \#] \w > " ;;
PS1="[\A - \$LOAD]\n[\h \#] \w > " ;;
esac
}
@ -144,6 +192,7 @@ alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# -> Prevents accidentally clobbering files.
alias mkdir='mkdir -p'
alias h='history'
alias j='jobs -l'
@ -151,23 +200,23 @@ alias r='rlogin'
alias which='type -all'
alias ..='cd ..'
alias path='echo -e ${PATH//:/\\n}'
alias print='/usr/bin/lp -o nobanner -d $LPDEST' # Assumes LPDEST is defined
alias print='/usr/bin/lp -o nobanner -d $LPDEST' # Assumes LPDEST is defined
alias pjet='enscript -h -G -fCourier9 -d $LPDEST' # Pretty-print using enscript
alias background='xv -root -quit -max -rmode 5' # put a picture in the background
alias vi='vim'
alias du='du -h'
alias df='df -kh'
alias background='xv -root -quit -max -rmode 5' # Put a picture in the background
alias du='du -kh'
alias df='df -kTh'
# The 'ls' family (this assumes you use the GNU ls)
alias la='ls -Al' # show hidden files
alias ls='ls -hF --color' # add colors for filetype recognition
alias lx='ls -lXB' # sort by extension
alias lk='ls -lSr' # sort by size
alias la='ls -Al' # show hidden files
alias lr='ls -lR' # recursice ls
alias lt='ls -ltr' # sort by date
alias lm='ls -al |more' # pipe through 'more'
alias tree='tree -Cs' # nice alternative to 'ls'
alias lx='ls -lXB' # sort by extension
alias lk='ls -lSr' # sort by size
alias lc='ls -lcr' # sort by change time
alias lu='ls -lur' # sort by access time
alias lr='ls -lR' # recursive ls
alias lt='ls -ltr' # sort by date
alias lm='ls -al |more' # pipe through 'more'
alias tree='tree -Csu' # nice alternative to 'ls'
# tailoring 'less'
alias more='less'
@ -190,10 +239,11 @@ alias kk='ll'
function xtitle ()
{
case $TERM in
case "$TERM" in
*term | rxvt)
echo -n -e "\033]0;$*\007" ;;
*) ;;
*)
;;
esac
}
@ -202,21 +252,22 @@ alias top='xtitle Processes on $HOST && top'
alias make='xtitle Making $(basename $PWD) ; make'
alias ncftp="xtitle ncFTP ; ncftp"
# .. and functions
# .. and functions
function man ()
{
xtitle The $(basename $1|tr -d .[:digit:]) manual
man -a "$*"
for i ; do
xtitle The $(basename $1|tr -d .[:digit:]) manual
command man -F -a "$i"
done
}
function ll(){ ls -l "$@"| egrep "^d" ; ls -lXB "$@" 2>&-| egrep -v "^d|total "; }
function xemacs() { { command xemacs -private $* 2>&- & } && disown ;}
function te() # wrapper around xemacs/gnuserv
{
if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then
gnuclient -q "$@";
else
( xemacs "$@" & );
( xemacs "$@" &);
fi
}
@ -224,18 +275,33 @@ function te() # wrapper around xemacs/gnuserv
# File & strings related functions:
#-----------------------------------
function ff() { find . -name '*'$1'*' ; } # find a file
function fe() { find . -name '*'$1'*' -exec $2 {} \; ; } # find a file and run $2 on it
function fstr() # find a string in a set of files
# Find a file with a pattern in name:
function ff() { find . -type f -iname '*'$*'*' -ls ; }
# Find a file with pattern $1 in name and Execute $2 on it:
function fe() { find . -type f -iname '*'$1'*' -exec "${2:-file}" {} \; ; }
# find pattern in a set of filesand highlight them:
function fstr()
{
if [ "$#" -gt 2 ]; then
echo "Usage: fstr \"pattern\" [files] "
OPTIND=1
local case=""
local usage="fstr: find string in files.
Usage: fstr [-i] \"pattern\" [\"filename pattern\"] "
while getopts :it opt
do
case "$opt" in
i) case="-i " ;;
*) echo "$usage"; return;;
esac
done
shift $(( $OPTIND - 1 ))
if [ "$#" -lt 1 ]; then
echo "$usage"
return;
fi
SMSO=$(tput smso)
RMSO=$(tput rmso)
find . -type f -name "${2:-*}" -print | xargs grep -sin "$1" | \
sed "s/$1/$SMSO$1$RMSO/gI"
local SMSO=$(tput smso)
local RMSO=$(tput rmso)
find . -type f -name "${2:-*}" -print0 | xargs -0 grep -sn ${case} "$1" 2>&- | \
sed "s/$1/${SMSO}\0${RMSO}/gI" | more
}
function cuttail() # cut last n lines in file, 10 by default
@ -266,11 +332,12 @@ function lowercase() # move filenames to lowercase
function swap() # swap 2 filenames around
{
local TMPFILE=tmp.$$
mv $1 $TMPFILE
mv $2 $1
mv $TMPFILE $2
mv "$1" $TMPFILE
mv "$2" "$1"
mv $TMPFILE "$2"
}
#-----------------------------------
# Process/system related functions:
#-----------------------------------
@ -283,16 +350,16 @@ function pp() { my_ps f | awk '!/awk/ && $0~var' var=${1:-".*"} ; }
function killps() # kill by process name
{
local pid pname sig="-TERM" # default signal
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo "Usage: killps [-SIGNAL] pattern"
return;
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo "Usage: killps [-SIGNAL] pattern"
return;
fi
if [ $# = 2 ]; then sig=$1 ; fi
for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) ; do
pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
if ask "Kill process $pid <$pname> with signal $sig?"
then kill $sig $pid
fi
pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
if ask "Kill process $pid <$pname> with signal $sig?"
then kill $sig $pid
fi
done
}
@ -316,7 +383,6 @@ function ii() # get current host related info
echo
}
# Misc utilities:
function repeat() # repeat n times command
@ -328,7 +394,6 @@ function repeat() # repeat n times command
done
}
function ask()
{
echo -n "$@" '[y/n] ' ; read ans
@ -341,8 +406,9 @@ function ask()
#=========================================================================
#
# PROGRAMMABLE COMPLETION - ONLY SINCE BASH-2.04
# (Most are taken from the bash 2.05 documentation)
# You will in fact need bash-2.05 for some features
# Most are taken from the bash 2.05 documentation and from Ian McDonalds
# 'Bash completion' package (http://www.caliban.org/bash/index.shtml#completion)
# You will in fact need bash-2.05a for some features
#
#=========================================================================
@ -352,11 +418,9 @@ if [ "${BASH_VERSION%.*}" \< "2.05" ]; then
fi
shopt -s extglob # necessary
set +o nounset # otherwise some completions will fail
set +o nounset # otherwise some completions will fail
complete -A hostname rsh rcp telnet rlogin r ftp ping disk
complete -A command nohup exec eval trace gdb
complete -A command command type which
complete -A export printenv
complete -A variable export local readonly unset
complete -A enabled builtin
@ -372,40 +436,57 @@ complete -A job -P '%' fg jobs disown
complete -A directory mkdir rmdir
complete -A directory -o default cd
complete -f -d -X '*.gz' gzip
complete -f -d -X '*.bz2' bzip2
complete -f -o default -X '!*.gz' gunzip
complete -f -o default -X '!*.bz2' bunzip2
complete -f -o default -X '!*.pl' perl perl5
# Compression
complete -f -o default -X '*.+(zip|ZIP)' zip
complete -f -o default -X '!*.+(zip|ZIP)' unzip
complete -f -o default -X '*.+(z|Z)' compress
complete -f -o default -X '!*.+(z|Z)' uncompress
complete -f -o default -X '*.+(gz|GZ)' gzip
complete -f -o default -X '!*.+(gz|GZ)' gunzip
complete -f -o default -X '*.+(bz2|BZ2)' bzip2
complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2
# Postscript,pdf,dvi.....
complete -f -o default -X '!*.ps' gs ghostview ps2pdf ps2ascii
complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype
complete -f -o default -X '!*.pdf' acroread pdf2ps
complete -f -o default -X '!*.+(pdf|ps)' gv
complete -f -o default -X '!*.pdf' acroread pdf2ps
complete -f -o default -X '!*.+(pdf|ps)' gv
complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
complete -f -o default -X '!*.tex' tex latex slitex
complete -f -o default -X '!*.lyx' lyx
complete -f -o default -X '!*.+(jpg|gif|xpm|png|bmp)' xv gimp
complete -f -o default -X '!*.mp3' mpg123
complete -f -o default -X '!*.ogg' ogg123
complete -f -o default -X '!*.tex' tex latex slitex
complete -f -o default -X '!*.lyx' lyx
complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps
# Multimedia
complete -f -o default -X '!*.+(jp*g|gif|xpm|png|bmp)' xv gimp
complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321
complete -f -o default -X '!*.+(ogg|OGG)' ogg123
complete -f -o default -X '!*.pl' perl perl5
# This is a 'universal' completion function - it works when commands have
# a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
_universal_func ()
# a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
_get_longopts ()
{
$1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \
grep ^"$2" |sort -u ;
}
_longopts_func ()
{
case "$2" in
case "${2:-*}" in
-*) ;;
*) return ;;
esac
case "$1" in
\~*) eval cmd=$1 ;;
\~*) eval cmd="$1" ;;
*) cmd="$1" ;;
esac
COMPREPLY=( $("$cmd" --help | sed -e '/--/!d' -e 's/.*--\([^ ]*\).*/--\1/'| \
grep ^"$2" |sort -u) )
COMPREPLY=( $(_get_longopts ${1} ${2} ) )
}
complete -o default -F _universal_func ldd wget bash id info
complete -o default -F _longopts_func configure bash
complete -o default -F _longopts_func wget id info a2ps ls recode
_make_targets ()
@ -459,22 +540,6 @@ _make_targets ()
complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake
_configure_func ()
{
case "$2" in
-*) ;;
*) return ;;
esac
case "$1" in
\~*) eval cmd=$1 ;;
*) cmd="$1" ;;
esac
COMPREPLY=( $("$cmd" --help | awk '{if ($1 ~ /--.*/) print $1}' | grep ^"$2" | sort -u) )
}
complete -F _configure_func configure
# cvs(1) completion
_cvs ()
@ -485,17 +550,16 @@ _cvs ()
prev=${COMP_WORDS[COMP_CWORD-1]}
if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
COMPREPLY=( $( compgen -W 'add admin checkout commit diff \
export history import log rdiff release remove rtag status \
tag update' $cur ))
COMPREPLY=( $( compgen -W 'add admin checkout commit diff \
export history import log rdiff release remove rtag status \
tag update' $cur ))
else
COMPREPLY=( $( compgen -f $cur ))
COMPREPLY=( $( compgen -f $cur ))
fi
return 0
}
complete -F _cvs cvs
_killall ()
{
local cur prev
@ -514,6 +578,60 @@ _killall ()
complete -F _killall killall killps
# A meta-command completion function for commands like sudo(8), which need to
# first complete on a command, then complete according to that command's own
# completion definition - currently not quite foolproof (e.g. mount and umount
# don't work properly), but still quite useful - By Ian McDonald, modified by me.
_my_command()
{
local cur func cline cspec
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
if [ $COMP_CWORD = 1 ]; then
COMPREPLY=( $( compgen -c $cur ) )
elif complete -p ${COMP_WORDS[1]} &>/dev/null; then
cspec=$( complete -p ${COMP_WORDS[1]} )
if [ "${cspec%%-F *}" != "${cspec}" ]; then
# complete -F &lt;function&gt;
#
# COMP_CWORD and COMP_WORDS() are not read-only,
# so we can set them before handing off to regular
# completion routine
# set current token number to 1 less than now
COMP_CWORD=$(( $COMP_CWORD - 1 ))
# get function name
func=${cspec#*-F }
func=${func%% *}
# get current command line minus initial command
cline="${COMP_LINE#$1 }"
# split current command line tokens into array
COMP_WORDS=( $cline )
$func $cline
elif [ "${cspec#*-[abcdefgjkvu]}" != "" ]; then
# complete -[abcdefgjkvu]
#func=$( echo $cspec | sed -e 's/^.*\(-[abcdefgjkvu]\).*$/\1/' )
func=$( echo $cspec | sed -e 's/^complete//' -e 's/[^ ]*$//' )
COMPREPLY=( $( eval compgen $func $cur ) )
elif [ "${cspec#*-A}" != "$cspec" ]; then
# complete -A &lt;type&gt;
func=${cspec#*-A }
func=${func%% *}
COMPREPLY=( $( compgen -A $func $cur ) )
fi
else
COMPREPLY=( $( compgen -f $cur ) )
fi
}
complete -o default -F _my_command nohup exec eval trace truss strace sotruss gdb
complete -o default -F _my_command command type which man nice
# Local Variables:
# mode:shell-script
# sh-shell:bash

View File

@ -81,7 +81,7 @@ echo "File \"$file\" blotted out and deleted."; echo
# 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/secure_del.html
# http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html
exit 0

View File

@ -24,10 +24,16 @@ do
filename=${file%.*c} # Strip ".mac" suffix off filename
#+ ('.*c' matches everything
#+ between '.' and 'c', inclusive).
$OPERATION $file > $filename.$SUFFIX
$OPERATION $file > "$filename.$SUFFIX"
# Redirect conversion to new filename.
rm -f $file # Delete original files after converting.
echo "$filename.$SUFFIX" # Log what is happening to stdout.
done
exit 0
# Exercise:
# --------
# As it stands, this script converts *all* the files in the current
#+ working directory.
# Modify it to work *only* on files with a ".mac" suffix.

View File

@ -1,6 +1,10 @@
#!/bin/bash
# empty-array.sh
# Thanks to Stephane Chazelas for the original example,
#+ and to Michael Zick for extending it.
# An empty array is not the same as an array with empty elements.
array0=( first second third )
@ -8,7 +12,9 @@ array1=( '' ) # "array1" has one empty element.
array2=( ) # No elements... "array2" is empty.
echo
ListArray()
{
echo
echo "Elements in array0: ${array0[@]}"
echo "Elements in array1: ${array1[@]}"
echo "Elements in array2: ${array2[@]}"
@ -20,7 +26,101 @@ echo
echo "Number of elements in array0 = ${#array0[*]}" # 3
echo "Number of elements in array1 = ${#array1[*]}" # 1 (surprise!)
echo "Number of elements in array2 = ${#array2[*]}" # 0
}
# ===================================================================
ListArray
# Try extending those arrays
# Adding an element to an array.
array0=( "${array0[@]}" "new1" )
array1=( "${array1[@]}" "new1" )
array2=( "${array2[@]}" "new1" )
ListArray
# or
array0[${#array0[*]}]="new2"
array1[${#array1[*]}]="new2"
array2[${#array2[*]}]="new2"
ListArray
# When extended as above; arrays are 'stacks'
# The above is the 'push'
# The stack 'height' is:
height=${#array2[@]}
echo
echo "Stack height for array2 = $height"
exit 0 # Thanks, S.C.
# The 'pop' is:
unset array2[${#array2[@]}-1] # Arrays are zero based
height=${#array2[@]}
echo
echo "POP"
echo "New stack height for array2 = $height"
ListArray
# List only 2nd and 3rd elements of array0
from=1 # Zero based numbering
to=2 #
declare -a array3=( ${array0[@]:1:2} )
echo
echo "Elements in array3: ${array3[@]}"
# Works like a string (array of characters)
# Try some other "string" forms
# Replacement
declare -a array4=( ${array0[@]/second/2nd} )
echo
echo "Elements in array4: ${array4[@]}"
# Replace all matching wildcarded string
declare -a array5=( ${array0[@]//new?/old} )
echo
echo "Elements in array5: ${array5[@]}"
# Just when you are getting the feel for this...
declare -a array6=( ${array0[@]#*new} )
echo # This one might surprise you
echo "Elements in array6: ${array6[@]}"
declare -a array7=( ${array0[@]#new1} )
echo # After array6 this should not be a surprise
echo "Elements in array7: ${array7[@]}"
# Which looks a lot like...
declare -a array8=( ${array0[@]/new1/} )
echo
echo "Elements in array8: ${array8[@]}"
# So what can one say about this?
# The string operations are performed on
#+ each of the elements in var[@] in succession.
# Therefore : BASH supports string vector operations
# If the result is a zero length string, that
#+ element disappears in the resulting assignment.
# Question, are those strings hard or soft quotes?
zap='new*'
declare -a array9=( ${array0[@]/$zap/} )
echo
echo "Elements in array9: ${array9[@]}"
# Just when you thought you where still in Kansas...
declare -a array10=( ${array0[@]#$zap} )
echo
echo "Elements in array10: ${array10[@]}"
# Compare array7 with array10
# Compare array8 with array9
# Answer, must be soft quotes.
exit 0

View File

@ -17,3 +17,9 @@ echo >>logfile
echo >>logfile
exit 0
# Exercise:
# --------
# Modify this script to track changes in /var/log/messages at intervals
#+ of 20 minutes.
# Hint: Use the "watch" command.

View File

@ -7,7 +7,7 @@ DOC_REQUEST=70
if [ "$1" = "-h" -o "$1" = "--help" ] # Request help.
then
echo; echo "Usage: $0 [directory-name]"; echo
cat "$0" | sed --silent -e '/DOCUMENTATIONXX$/,/^DOCUMENTATION/p' |
sed --silent -e '/DOCUMENTATIONXX$/,/^DOCUMENTATION/p' "$0" |
sed -e '/DOCUMENTATIONXX/d'; exit $DOC_REQUEST; fi
: << DOCUMENTATIONXX

View File

@ -1,6 +1,6 @@
#!/bin/sh
# @(#) tree 1.1 30/11/95 by Jordi Sanfeliu
# email: mikaku@arrakis.es
# email: mikaku@fiwix.org
#
# Initial version: 1.0 30/11/95
# Next version : 1.1 24/02/97 Now, with symbolic links