mirror of https://github.com/tLDP/LDP
updated
This commit is contained in:
parent
738864a37c
commit
1023b2f15b
|
@ -3,6 +3,80 @@ RELEASE HISTORY
|
||||||
Change log
|
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)
|
Version 1.7 (minor update)
|
||||||
'COCONUT' release
|
'COCONUT' release
|
||||||
01/05/03
|
01/05/03
|
||||||
|
|
|
@ -17,6 +17,8 @@ read-r.sh
|
||||||
rnd.sh
|
rnd.sh
|
||||||
rot13.sh
|
rot13.sh
|
||||||
here-function.sh
|
here-function.sh
|
||||||
|
directory-info.sh (lines 273 and 353)
|
||||||
|
bashrc (comments on lines 596 and 618)
|
||||||
|
|
||||||
have the "<" and ">" in place of angle brackets (< and >), or & in
|
have the "<" and ">" in place of angle brackets (< and >), or & in
|
||||||
place of the ampersand (&). This is necessary for the Docbook SGML
|
place of the ampersand (&). This is necessary for the Docbook SGML
|
||||||
|
|
|
@ -268,6 +268,8 @@ Uncomment line below to generate index.
|
||||||
<!ENTITY brokenlink SYSTEM "broken-link.sh">
|
<!ENTITY brokenlink SYSTEM "broken-link.sh">
|
||||||
<!ENTITY continuenex SYSTEM "continue-n.example">
|
<!ENTITY continuenex SYSTEM "continue-n.example">
|
||||||
<!ENTITY pickcard SYSTEM "pick-card.sh">
|
<!ENTITY pickcard SYSTEM "pick-card.sh">
|
||||||
|
<!ENTITY copyarray SYSTEM "CopyArray.sh">
|
||||||
|
<!ENTITY directoryinfo SYSTEM "directory-info.sh">
|
||||||
<!ENTITY evalex SYSTEM "eval.example">
|
<!ENTITY evalex SYSTEM "eval.example">
|
||||||
<!ENTITY namesdata SYSTEM "names.data">
|
<!ENTITY namesdata SYSTEM "names.data">
|
||||||
<!ENTITY gen0data SYSTEM "gen0">
|
<!ENTITY gen0data SYSTEM "gen0">
|
||||||
|
@ -277,20 +279,20 @@ Uncomment line below to generate index.
|
||||||
<book>
|
<book>
|
||||||
<bookinfo>
|
<bookinfo>
|
||||||
<title>Advanced Bash-Scripting Guide</title>
|
<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>
|
<author>
|
||||||
<firstname>Mendel</firstname>
|
<firstname>Mendel</firstname>
|
||||||
<surname>Cooper</surname>
|
<surname>Cooper</surname>
|
||||||
<affiliation>
|
<affiliation>
|
||||||
<orgname>Brindle-Phlogiston Associates</orgname>
|
<orgname></orgname>
|
||||||
<address><email>thegrendel@theriver.com</email></address>
|
<address><email>thegrendel@theriver.com</email></address>
|
||||||
</affiliation>
|
</affiliation>
|
||||||
</author>
|
</author>
|
||||||
|
|
||||||
<releaseinfo>1.7</releaseinfo>
|
<releaseinfo>1.8</releaseinfo>
|
||||||
<pubdate>05 January 2003</pubdate>
|
<pubdate>10 May 2003</pubdate>
|
||||||
|
|
||||||
|
|
||||||
<revhistory>
|
<revhistory>
|
||||||
|
@ -395,6 +397,14 @@ Uncomment line below to generate index.
|
||||||
more script.</revremark>
|
more script.</revremark>
|
||||||
</revision>
|
</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>
|
</revhistory>
|
||||||
|
|
||||||
|
|
||||||
|
@ -402,7 +412,7 @@ Uncomment line below to generate index.
|
||||||
|
|
||||||
<para>This tutorial assumes no previous knowledge of
|
<para>This tutorial assumes no previous knowledge of
|
||||||
scripting or programming, but progresses rapidly toward an
|
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
|
the while sneaking in little snippets of UNIX wisdom and
|
||||||
lore</emphasis>. It serves as a textbook, a manual for
|
lore</emphasis>. It serves as a textbook, a manual for
|
||||||
self-study, and a reference and source of knowledge on shell
|
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>
|
linkend="bzipref">bzip2-ed</link> <quote>tarball</quote>
|
||||||
including both the SGML source and
|
including both the SGML source and
|
||||||
rendered HTML, may be downloaded from <ulink
|
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
|
the author's home site</ulink>. See the <ulink
|
||||||
url="http://personal.riverusers.com/~thegrendel/Change.log">change
|
url="http://personal.riverusers.com/~thegrendel/Change.log">change
|
||||||
log</ulink> for a revision history.</para>
|
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
|
<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
|
even if they do not anticipate ever having to actually write a
|
||||||
script. Consider that as a Linux machine boots up, it executes the
|
script. Consider that as a Linux machine boots up, it executes the
|
||||||
shell scripts in <filename class="directory">/etc/rc.d</filename>
|
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>
|
<para>cross-platform portability required (use C instead)</para>
|
||||||
</listitem> <listitem>
|
</listitem> <listitem>
|
||||||
<para>complex applications, where structured programming is
|
<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>
|
prototypes, etc.)</para>
|
||||||
</listitem> <listitem>
|
</listitem> <listitem>
|
||||||
<para>mission-critical applications upon which you are betting the
|
<para>mission-critical applications upon which you are betting the
|
||||||
|
@ -539,8 +549,9 @@ Uncomment line below to generate index.
|
||||||
</listitem> <listitem>
|
</listitem> <listitem>
|
||||||
<para>need to use libraries or interface with legacy code</para>
|
<para>need to use libraries or interface with legacy code</para>
|
||||||
</listitem> <listitem>
|
</listitem> <listitem>
|
||||||
<para>proprietary, closed-source applications (shell scripts are
|
<para>proprietary, closed-source applications (shell scripts put the
|
||||||
necessarily Open Source)</para>
|
source code right out in the open for all the world to see)</para>
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist></para>
|
</itemizedlist></para>
|
||||||
|
|
||||||
|
@ -562,19 +573,19 @@ Uncomment line below to generate index.
|
||||||
and even a few from the updated <emphasis>ksh93</emphasis>
|
and even a few from the updated <emphasis>ksh93</emphasis>
|
||||||
have been merged into Bash.</para></footnote>
|
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
|
is not recommended due to certain inherent problems, as pointed out
|
||||||
in an October, 1993 <ulink
|
in an October, 1993 <ulink
|
||||||
url="http://www.etext.org/Quartz/computer/unix/csh.harmful.gz">Usenet
|
url="http://www.etext.org/Quartz/computer/unix/csh.harmful.gz">Usenet
|
||||||
post</ulink> by Tom Christiansen).
|
post</ulink> by Tom Christiansen.)
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>What follows is a tutorial on shell scripting. It relies
|
<para>What follows is a tutorial on shell scripting. It relies
|
||||||
heavily on examples to illustrate various features of the shell.
|
heavily on examples to illustrate various features of the shell.
|
||||||
As far as possible, the example scripts have been tested,
|
The example scripts work -- they've been tested -- and some
|
||||||
and some of them may even be useful in real life. The
|
of them are even useful in real life. The reader can play with
|
||||||
reader should use the actual examples in the source archive
|
the actual working code of the examples in the source archive
|
||||||
(<filename>something-or-other.sh</filename>),
|
(<filename>scriptname.sh</filename>),
|
||||||
|
|
||||||
<footnote><para>By convention, user-written shell scripts that are
|
<footnote><para>By convention, user-written shell scripts that are
|
||||||
Bourne shell compliant generally take a name with a
|
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
|
give them execute permission (<userinput>chmod u+rx
|
||||||
scriptname</userinput>), then run them to see what happens.
|
scriptname</userinput>), then run them to see what happens.
|
||||||
Should the source archive not be available, then cut-and-paste from
|
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,
|
the scripts below introduce features before they are explained,
|
||||||
and this may require the reader to temporarily skip ahead for
|
and this may require the reader to temporarily skip ahead for
|
||||||
enlightenment.</para>
|
enlightenment.</para>
|
||||||
|
|
||||||
<para>Unless otherwise noted, the book author wrote the example
|
<para>Unless otherwise noted, the author of this book wrote the
|
||||||
scripts that follow.</para>
|
example scripts that follow.</para>
|
||||||
|
|
||||||
</chapter> <!-- Why Shell Programming? -->
|
</chapter> <!-- Why Shell Programming? -->
|
||||||
|
|
||||||
|
@ -906,9 +917,9 @@ fi</programlisting>
|
||||||
<note><para>Of course, an escaped <token>#</token> in an
|
<note><para>Of course, an escaped <token>#</token> in an
|
||||||
<command>echo</command> statement does
|
<command>echo</command> statement does
|
||||||
<emphasis>not</emphasis> begin a comment. Likewise, a
|
<emphasis>not</emphasis> begin a comment. Likewise, a
|
||||||
<token>#</token> appears in <link linkend="psub2">certain
|
<token>#</token> appears in <link linkend="psub2">certain parameter
|
||||||
parameter substitution constructs</link> and in <link
|
substitution constructs</link> and in <link linkend="numconstants">
|
||||||
linkend="numconstants">numerical constant expressions</link>.
|
numerical constant expressions</link>.
|
||||||
|
|
||||||
<programlisting>echo "The # here does not begin a comment."
|
<programlisting>echo "The # here does not begin a comment."
|
||||||
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">
|
<sect1 id="untyped">
|
||||||
<title>Bash Variables Are Untyped</title>
|
<title>Bash Variables Are Untyped</title>
|
||||||
|
|
||||||
|
<para><anchor id="bvuntyped"></para>
|
||||||
<para>Unlike many other programming languages, Bash does not segregate
|
<para>Unlike many other programming languages, Bash does not segregate
|
||||||
its variables by <quote>type</quote>. Essentially, Bash
|
its variables by <quote>type</quote>. Essentially, Bash
|
||||||
variables are character strings, but, depending on context, Bash
|
variables are character strings, but, depending on context, Bash
|
||||||
|
@ -2946,10 +2958,11 @@ arch=$(uname -m)</programlisting></para>
|
||||||
any other process.</para>
|
any other process.</para>
|
||||||
|
|
||||||
<para>Every time a shell starts, it creates shell variables that
|
<para>Every time a shell starts, it creates shell variables that
|
||||||
correspond to its own environmental variables. Updating or
|
correspond to its own environmental variables. Updating
|
||||||
adding new shell variables causes the shell to update its
|
or adding new environmental variables causes the shell
|
||||||
environment, and all the shell's child processes (the commands
|
to update its environment, and all the shell's child
|
||||||
it executes) inherit this environment.</para>
|
processes (the commands it executes) inherit this
|
||||||
|
environment.</para>
|
||||||
|
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
|
@ -3185,8 +3198,45 @@ fi
|
||||||
enclose it in double quotes (<token>" "</token>). This
|
enclose it in double quotes (<token>" "</token>). This
|
||||||
preserves all special characters within the variable name,
|
preserves all special characters within the variable name,
|
||||||
except <token>$</token>, <token>`</token> (backquote),
|
except <token>$</token>, <token>`</token> (backquote),
|
||||||
and <token>\</token> (escape). Keeping <token>$</token>
|
and <token>\</token> (escape).
|
||||||
as a special character permits referencing a quoted variable
|
|
||||||
|
<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
|
(<replaceable>"$variable"</replaceable>), that is, replacing the
|
||||||
variable with its value (see <xref linkend="ex9">, above).</para>
|
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>
|
<command>if/then</command> construct.</para>
|
||||||
|
|
||||||
<sect1 id="testconstructs">
|
<sect1 id="testconstructs">
|
||||||
<title><anchor id="testconstructs1">Test Constructs</title>
|
<title>Test Constructs</title>
|
||||||
|
|
||||||
|
<para><anchor id="testconstructs1"></para>
|
||||||
|
|
||||||
<itemizedlist id="testingref">
|
<itemizedlist id="testingref">
|
||||||
|
|
||||||
|
@ -3993,8 +4045,8 @@ fi</programlisting>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para><anchor id="dblbrackets">The <token>[[ ]]</token> construct
|
<para><anchor id="dblbrackets">The <token>[[ ]]</token> construct
|
||||||
is the shell equivalent of <token>[ ]</token>. This is the
|
is the more versatile Bash version of <token>[ ]</token>. This
|
||||||
<emphasis>extended test command</emphasis>, adopted from
|
is the <emphasis>extended test command</emphasis>, adopted from
|
||||||
<emphasis>ksh88</emphasis>.</para>
|
<emphasis>ksh88</emphasis>.</para>
|
||||||
|
|
||||||
<note><para>No filename expansion or word splitting takes place
|
<note><para>No filename expansion or word splitting takes place
|
||||||
|
@ -6468,7 +6520,28 @@ echo "$@" # 3 4 5
|
||||||
<secondary>last job background</secondary>
|
<secondary>last job background</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
||||||
<para>PID (process id) of last job run in background</para>
|
<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>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -8791,6 +8864,19 @@ done</programlisting></para>
|
||||||
linkend="oldpwd">$OLDPWD</link>, the previous working
|
linkend="oldpwd">$OLDPWD</link>, the previous working
|
||||||
directory.</para>
|
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>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -10914,11 +11000,17 @@ find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \
|
||||||
<programlisting>sleep 3
|
<programlisting>sleep 3
|
||||||
# Pauses 3 seconds.</programlisting>
|
# Pauses 3 seconds.</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note><para>The <command>sleep</command> command defaults to
|
<note><para>The <command>sleep</command> command defaults to
|
||||||
seconds, but minute, hours, or days may also be specified.
|
seconds, but minute, hours, or days may also be specified.
|
||||||
<programlisting>sleep 3 h
|
<programlisting>sleep 3 h
|
||||||
# Pauses 3 hours!</programlisting>
|
# Pauses 3 hours!</programlisting>
|
||||||
</para></note>
|
</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>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -13142,6 +13234,9 @@ gzip -cd patchXX.gz | patch -p0
|
||||||
<programlisting>&fileintegrity;</programlisting>
|
<programlisting>&fileintegrity;</programlisting>
|
||||||
</example>
|
</example>
|
||||||
|
|
||||||
|
<para>See also <xref linkend="directoryinfo"> for a creative use of
|
||||||
|
the <command>md5sum</command> command.</para>
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -13348,6 +13443,23 @@ echo "tempfile name = $tempfile"
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
<varlistentry>
|
||||||
<term><command>ptx</command></term>
|
<term><command>ptx</command></term>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
|
@ -17609,6 +17721,24 @@ print "even when I don't know where to find Perl.\n";
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
<varlistentry>
|
||||||
<term><command>strip</command></term>
|
<term><command>strip</command></term>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
|
@ -17849,7 +17979,11 @@ echo "$dir_listing" # quoted
|
||||||
<programlisting>variable1=`<file1` # Set "variable1" to contents of "file1".
|
<programlisting>variable1=`<file1` # Set "variable1" to contents of "file1".
|
||||||
variable2=`cat file2` # Set "variable2" to contents of "file2".
|
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>
|
#+ or even (horrors), control characters.</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -17951,8 +18085,11 @@ echo $greeting</programlisting>
|
||||||
|
|
||||||
<note><para>The <command>$(COMMAND)</command> form has
|
<note><para>The <command>$(COMMAND)</command> form has
|
||||||
superseded backticks for command substitution.
|
superseded backticks for command substitution.
|
||||||
<programlisting>output=$(sed -n /"$1"/p $file)
|
<programlisting>output=$(sed -n /"$1"/p $file) # From "grp.sh" example.
|
||||||
# From "grp.sh" example.</programlisting></para></note>
|
|
||||||
|
# Setting a variable to the contents of a text file.
|
||||||
|
File_contents1=$(cat $file1)
|
||||||
|
File_contents2=$(<$file2) # Bash permits this also.</programlisting></para></note>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18003,7 +18140,7 @@ echo $greeting</programlisting>
|
||||||
</indexterm> <indexterm>
|
</indexterm> <indexterm>
|
||||||
<primary>arithmetic</primary> <secondary>expansion</secondary>
|
<primary>arithmetic</primary> <secondary>expansion</secondary>
|
||||||
</indexterm> <listitem>
|
</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>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -18026,12 +18163,13 @@ echo $greeting</programlisting>
|
||||||
convenient <command>let</command> construction.
|
convenient <command>let</command> construction.
|
||||||
|
|
||||||
<programlisting>z=$(($z+3))
|
<programlisting>z=$(($z+3))
|
||||||
# $((EXPRESSION)) is arithmetic expansion. # Not to be confused with
|
# $((EXPRESSION)) is arithmetic expansion. # Not to be confused with
|
||||||
# command substitution.
|
#+ command substitution.
|
||||||
|
|
||||||
let z=z+3
|
let z=z+3
|
||||||
let "z += 3" #If quotes, then spaces and special operators allowed.
|
let "z += 3" # Quotes permit the use of spaces and special operators.
|
||||||
# 'let' is actually arithmetic evaluation, rather than expansion.</programlisting>
|
# The 'let' operator actually performs arithmetic evaluation,
|
||||||
|
#+ rather than expansion.</programlisting>
|
||||||
|
|
||||||
All the above are equivalent. You may use whichever one
|
All the above are equivalent. You may use whichever one
|
||||||
<quote>rings your chimes</quote>.
|
<quote>rings your chimes</quote>.
|
||||||
|
@ -19767,9 +19905,12 @@ route -n |
|
||||||
<para>The function definition must precede the first call to
|
<para>The function definition must precede the first call to
|
||||||
it. There is no method of <quote>declaring</quote> the function,
|
it. There is no method of <quote>declaring</quote> the function,
|
||||||
as, for example, in C.
|
as, for example, in C.
|
||||||
<programlisting># f1
|
<programlisting>f1
|
||||||
# Will give an error message, since function "f1" not yet defined.
|
# 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...
|
# However...
|
||||||
|
|
||||||
|
|
||||||
|
@ -19784,11 +19925,11 @@ f2 ()
|
||||||
echo "Function \"f2\"."
|
echo "Function \"f2\"."
|
||||||
}
|
}
|
||||||
|
|
||||||
f1 # Function "f2" is not actually called until this point,
|
f1 # Function "f2" is not actually called until this point,
|
||||||
# although it is referenced before its definition.
|
#+ although it is referenced before its definition.
|
||||||
# This is permissable.
|
# This is permissable.
|
||||||
|
|
||||||
# Thanks, S.C.</programlisting>
|
# Thanks, S.C.</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>It is even possible to nest a function within another function,
|
<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
|
f2 # Gives an error message.
|
||||||
# Gives an error message.
|
# Even a preceding "declare -f f2" wouldn't help.
|
||||||
|
|
||||||
f1 # Does nothing, since calling "f1" does not automatically call "f2".
|
echo
|
||||||
f2 # Now, it's all right to call "f2",
|
|
||||||
# since its definition has been made visible by calling "f1".
|
|
||||||
|
|
||||||
# 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>
|
||||||
|
|
||||||
<para>Function declarations can appear in unlikely places, even where a
|
<para>Function declarations can appear in unlikely places, even where a
|
||||||
|
@ -20419,6 +20562,25 @@ false && ( true || echo false ) # (nothing echoed)
|
||||||
<programlisting>&ex66;</programlisting>
|
<programlisting>&ex66;</programlisting>
|
||||||
</example>
|
</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">
|
<example id="poem">
|
||||||
<title>Formatting a poem</title>
|
<title>Formatting a poem</title>
|
||||||
<programlisting>&poem;</programlisting>
|
<programlisting>&poem;</programlisting>
|
||||||
|
@ -20522,7 +20684,15 @@ element_count=${#array1[*]}
|
||||||
echo $element_count # 8</programlisting>
|
echo $element_count # 8</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
|
<para>Clever scripting makes it possible to add array operations.</para>
|
||||||
|
|
||||||
|
<example id="copyarray">
|
||||||
|
<title>Copying and concatenating arrays</title>
|
||||||
|
<programlisting>©array;</programlisting>
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<para>--</para>
|
||||||
|
|
||||||
<para>Arrays permit deploying old familiar algorithms as shell scripts.
|
<para>Arrays permit deploying old familiar algorithms as shell scripts.
|
||||||
Whether this is necessarily a good idea is left to the reader to
|
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>--</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
|
<para>Arrays enable implementing a shell script version of the <emphasis>Sieve of
|
||||||
Eratosthenes</emphasis>. Of course, a resource-intensive application of this
|
Eratosthenes</emphasis>. Of course, a resource-intensive application of this
|
||||||
nature should really be written in a compiled language, such as C. It
|
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>
|
</programlisting></para>
|
||||||
|
|
||||||
|
|
||||||
|
<para><anchor id="invocationoptionsref"></para>
|
||||||
<para>It is also possible to enable script options from the command
|
<para>It is also possible to enable script options from the command
|
||||||
line. Some options that will not work with
|
line. Some options that will not work with
|
||||||
<command>set</command> are available this way. Among these
|
<command>set</command> are available this way. Among these
|
||||||
|
@ -21471,9 +21664,9 @@ do_something do_something
|
||||||
|
|
||||||
|
|
||||||
<para><anchor id="wsbad">Using <link
|
<para><anchor id="wsbad">Using <link
|
||||||
linkend="whitespaceref">whitespace</link> inappropriately
|
linkend="whitespaceref">whitespace</link> inappropriately.
|
||||||
(in contrast to other programming languages, Bash can be quite
|
In contrast to other programming languages, Bash can be quite
|
||||||
finicky about whitespace).
|
finicky about whitespace.
|
||||||
|
|
||||||
<programlisting>var1 = 23 # 'var1=23' is correct.
|
<programlisting>var1 = 23 # 'var1=23' is correct.
|
||||||
# On line above, Bash attempts to execute command "var1"
|
# 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>
|
# [[ $a -le 5 ]] also works.</programlisting>
|
||||||
</para>
|
</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
|
assigned to them) are <quote>zeroed out</quote>. An
|
||||||
uninitialized variable has a value of <quote>null</quote>,
|
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
|
<para>Mixing up <emphasis>=</emphasis> and <emphasis>-eq</emphasis> in
|
||||||
a test. Remember, <emphasis>=</emphasis> is for comparing literal
|
a test. Remember, <emphasis>=</emphasis> is for comparing literal
|
||||||
|
@ -21593,11 +21794,27 @@ fi
|
||||||
<command>sh</command> to <command>bash</command>, but this does
|
<command>sh</command> to <command>bash</command>, but this does
|
||||||
not necessarily hold true for a generic UNIX machine.</para>
|
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>
|
will fail to execute, since <userinput>#!/bin/bash\r\n</userinput>
|
||||||
is not recognized, <emphasis>not</emphasis> the same as the
|
is not recognized, <emphasis>not</emphasis> the same as the
|
||||||
expected <userinput>#!/bin/bash\n</userinput>. The fix is to
|
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>
|
<para>A shell script headed by <userinput>#!/bin/sh</userinput>
|
||||||
may not run in full Bash-compatibility mode. Some Bash-specific
|
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
|
undesirable behavior as far as CGI is concerned. Moreover, it is
|
||||||
difficult to <quote>cracker-proof</quote> shell scripts.</para>
|
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
|
<para>Bash scripts written for Linux or BSD systems may need
|
||||||
fixups to run on a commercial UNIX machine. Such scripts
|
fixups to run on a commercial UNIX machine. Such scripts
|
||||||
often employ GNU commands and filters which have greater
|
often employ GNU commands and filters which have greater
|
||||||
|
@ -22796,12 +23016,46 @@ fi</programlisting>
|
||||||
features to the latest versions of Bash.</para>
|
features to the latest versions of Bash.</para>
|
||||||
|
|
||||||
<para>On a commercial UNIX machine, scripts using GNU-specific
|
<para>On a commercial UNIX machine, scripts using GNU-specific
|
||||||
features of standard commands may not work. This has become
|
features of standard commands may not work. This has become less
|
||||||
less of a problem in the last few years, as the GNU utilities
|
of a problem in the last few years, as the GNU utilities have
|
||||||
have pretty much displaced their proprietary counterparts even
|
pretty much displaced their proprietary counterparts even on
|
||||||
on <quote>big-iron</quote> UNIX. Caldera's recent release of
|
<quote>big-iron</quote> UNIX. Caldera's release of the source
|
||||||
the source to many of the original UNIX utilities will only
|
to many of the original UNIX utilities will only accelerate
|
||||||
accelerate the trend.</para>
|
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 -->
|
</sect1> <!-- Portability Issues -->
|
||||||
|
|
||||||
|
@ -23035,7 +23289,7 @@ fi</programlisting>
|
||||||
an instructive example script.</para>
|
an instructive example script.</para>
|
||||||
|
|
||||||
<para>Many thanks to <ulink
|
<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
|
for giving permission to use his fine tree script (<xref
|
||||||
linkend="tree">).</para>
|
linkend="tree">).</para>
|
||||||
|
|
||||||
|
@ -23075,6 +23329,10 @@ fi</programlisting>
|
||||||
linkend="cutref">cut</link> and <link
|
linkend="cutref">cut</link> and <link
|
||||||
linkend="pidofref">pidof</link>.</para>
|
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>Marc-Jano Knopp sent corrections on DOS batch files.</para>
|
||||||
|
|
||||||
<para>Hyun Jin Cha found several typos in the document in the
|
<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>
|
<author><firstname>Aeleen</firstname><surname>Frisch</surname></author>
|
||||||
</authorgroup>
|
</authorgroup>
|
||||||
<title>Essential System Administration</title>
|
<title>Essential System Administration</title>
|
||||||
<edition>2nd edition</edition>
|
<edition>3rd edition</edition>
|
||||||
<publisher>
|
<publisher>
|
||||||
<publishername>O'Reilly and Associates</publishername>
|
<publishername>O'Reilly and Associates</publishername>
|
||||||
</publisher>
|
</publisher>
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>1995</year>
|
<year>2002</year>
|
||||||
</copyright>
|
</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
|
<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
|
scripting for sys administrators and does a nice job of explaining the
|
||||||
startup and initialization scripts. The book is long overdue for a third
|
startup and initialization scripts. The long overdue third edition of this
|
||||||
edition (are you listening, Tim O'Reilly?).</para>
|
classic has finally been released.</para>
|
||||||
<para>*</para>
|
<para>*</para>
|
||||||
</abstract>
|
</abstract>
|
||||||
</biblioentry>
|
</biblioentry>
|
||||||
|
@ -23459,21 +23717,20 @@ fi</programlisting>
|
||||||
|
|
||||||
<biblioentry>
|
<biblioentry>
|
||||||
<title>The UNIX CD Bookshelf</title>
|
<title>The UNIX CD Bookshelf</title>
|
||||||
<edition>2nd edition</edition>
|
<edition>3rd edition</edition>
|
||||||
<publisher>
|
<publisher>
|
||||||
<publishername>O'Reilly and Associates</publishername>
|
<publishername>O'Reilly and Associates</publishername>
|
||||||
</publisher>
|
</publisher>
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2000</year>
|
<year>2003</year>
|
||||||
</copyright>
|
</copyright>
|
||||||
<isbn>1-56592-815-6</isbn>
|
<isbn>0-596-00392-7</isbn>
|
||||||
<abstract><para>An array of six UNIX books on CD ROM, including
|
<abstract><para>An array of seven UNIX books on CD ROM, including
|
||||||
<emphasis>UNIX Power Tools</emphasis>, <emphasis>Sed
|
<emphasis>UNIX Power Tools</emphasis>, <emphasis>Sed
|
||||||
and Awk</emphasis>, and <emphasis>Learning the Korn
|
and Awk</emphasis>, and <emphasis>Learning the Korn
|
||||||
Shell</emphasis>. A complete set of all the UNIX references
|
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>
|
even if it means going into debt and not paying the rent.</para>
|
||||||
<para>Unfortunately, out of print at present.</para>
|
|
||||||
<para>*</para>
|
<para>*</para>
|
||||||
</abstract>
|
</abstract>
|
||||||
</biblioentry>
|
</biblioentry>
|
||||||
|
@ -23545,8 +23802,7 @@ fi</programlisting>
|
||||||
<biblioentry>
|
<biblioentry>
|
||||||
<abstract>
|
<abstract>
|
||||||
<para>Example shell scripts at <ulink
|
<para>Example shell scripts at <ulink
|
||||||
url="http://www.oase-shareware.org/shell/scripts">SHELLdorado
|
url="http://www.shelldorado.com">SHELLdorado </ulink>.</para>
|
||||||
</ulink>.</para>
|
|
||||||
</abstract>
|
</abstract>
|
||||||
</biblioentry>
|
</biblioentry>
|
||||||
|
|
||||||
|
@ -23577,19 +23833,11 @@ fi</programlisting>
|
||||||
<biblioentry>
|
<biblioentry>
|
||||||
<abstract>
|
<abstract>
|
||||||
<para>Giles Orr's <ulink
|
<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>
|
HOWTO</ulink>.</para>
|
||||||
</abstract>
|
</abstract>
|
||||||
</biblioentry>
|
</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>
|
<biblioentry>
|
||||||
<abstract>
|
<abstract>
|
||||||
<para>Very nice <command>sed</command>,
|
<para>Very nice <command>sed</command>,
|
||||||
|
@ -23599,6 +23847,14 @@ fi</programlisting>
|
||||||
</abstract>
|
</abstract>
|
||||||
</biblioentry>
|
</biblioentry>
|
||||||
|
|
||||||
|
<biblioentry>
|
||||||
|
<abstract>
|
||||||
|
<para>Eric Pement's
|
||||||
|
<ulink url="http://www.student.northpark.edu/pemente/sed/">sed resources page</ulink>.</para>
|
||||||
|
</abstract>
|
||||||
|
</biblioentry>
|
||||||
|
|
||||||
|
|
||||||
<biblioentry>
|
<biblioentry>
|
||||||
<abstract>
|
<abstract>
|
||||||
<para>The GNU <command>gawk</command> <ulink
|
<para>The GNU <command>gawk</command> <ulink
|
||||||
|
@ -23839,6 +24095,16 @@ fi</programlisting>
|
||||||
<programlisting>&string;</programlisting>
|
<programlisting>&string;</programlisting>
|
||||||
</example>
|
</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
|
<para>Stephane Chazelas demonstrates object-oriented programming in a
|
||||||
Bash script.</para>
|
Bash script.</para>
|
||||||
|
|
||||||
|
|
|
@ -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.
|
# This file is read (normally) by interactive shells only.
|
||||||
# Here is the place to define your aliases, functions and
|
# Here is the place to define your aliases, functions and
|
||||||
# other interactive features like your prompt.
|
# 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.
|
# --> 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
|
# 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.
|
# --> Comments added by HOWTO author.
|
||||||
|
# --> And then edited again by ER :-)
|
||||||
|
|
||||||
#-----------------------------------
|
#-----------------------------------
|
||||||
# Source global definitions (if any)
|
# Source global definitions (if any)
|
||||||
|
@ -25,38 +32,69 @@ fi
|
||||||
|
|
||||||
#-------------------------------------------------------------
|
#-------------------------------------------------------------
|
||||||
# Automatic setting of $DISPLAY (if not set already)
|
# 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
|
if [ -z ${DISPLAY:=""} ]; then
|
||||||
DISPLAY=$(who am i)
|
get_xserver
|
||||||
DISPLAY=${DISPLAY%%\!*}
|
if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || ${XSERVER} == "unix" ]]; then
|
||||||
if [ -n "$DISPLAY" ]; then
|
DISPLAY=":0.0" # Display on local host
|
||||||
export DISPLAY=$DISPLAY:0.0
|
else
|
||||||
else
|
DISPLAY=${XSERVER}:0.0 # Display on remote host
|
||||||
export DISPLAY=":0.0" # fallback
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export DISPLAY
|
||||||
|
|
||||||
#---------------
|
#---------------
|
||||||
# Some settings
|
# Some settings
|
||||||
#---------------
|
#---------------
|
||||||
|
|
||||||
|
ulimit -S -c 0 # Don't want any coredumps
|
||||||
set -o notify
|
set -o notify
|
||||||
set -o noclobber
|
set -o noclobber
|
||||||
set -o ignoreeof
|
set -o ignoreeof
|
||||||
set -o nounset
|
set -o nounset
|
||||||
#set -o xtrace # useful for debuging
|
#set -o xtrace # useful for debuging
|
||||||
|
|
||||||
|
# Enable options:
|
||||||
shopt -s cdspell
|
shopt -s cdspell
|
||||||
shopt -s cdable_vars
|
shopt -s cdable_vars
|
||||||
shopt -s checkhash
|
shopt -s checkhash
|
||||||
shopt -s checkwinsize
|
shopt -s checkwinsize
|
||||||
shopt -s mailwarn
|
shopt -s mailwarn
|
||||||
shopt -s sourcepath
|
shopt -s sourcepath
|
||||||
shopt -s no_empty_cmd_completion
|
shopt -s no_empty_cmd_completion # bash>=2.04 only
|
||||||
shopt -s histappend histreedit
|
shopt -s cmdhist
|
||||||
shopt -s extglob # useful for programmable completion
|
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...
|
# Greeting, motd etc...
|
||||||
|
@ -75,26 +113,37 @@ NC='\e[0m' # No Color
|
||||||
# Looks best on a black background.....
|
# Looks best on a black background.....
|
||||||
echo -e "${CYAN}This is BASH ${RED}${BASH_VERSION%.*}${CYAN} - DISPLAY on ${RED}$DISPLAY${NC}\n"
|
echo -e "${CYAN}This is BASH ${RED}${BASH_VERSION%.*}${CYAN} - DISPLAY on ${RED}$DISPLAY${NC}\n"
|
||||||
date
|
date
|
||||||
if [ -x /usr/games/fortune ]; then
|
if [ -x /usr/games/fortune ]; then
|
||||||
/usr/games/fortune -s # makes our day a bit more fun.... :-)
|
/usr/games/fortune -s # makes our day a bit more fun.... :-)
|
||||||
fi
|
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}"
|
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()
|
function fastprompt()
|
||||||
{
|
{
|
||||||
unset PROMPT_COMMAND
|
unset PROMPT_COMMAND
|
||||||
case $TERM in
|
case $TERM in
|
||||||
*term | rxvt )
|
*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 > " ;;
|
PS1="[\h] \W > " ;;
|
||||||
esac
|
esac
|
||||||
|
@ -105,17 +154,16 @@ function powerprompt()
|
||||||
_powerprompt()
|
_powerprompt()
|
||||||
{
|
{
|
||||||
LOAD=$(uptime|sed -e "s/.*: \([^,]*\).*/\1/" -e "s/ //g")
|
LOAD=$(uptime|sed -e "s/.*: \([^,]*\).*/\1/" -e "s/ //g")
|
||||||
TIME=$(date +%H:%M)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PROMPT_COMMAND=_powerprompt
|
PROMPT_COMMAND=_powerprompt
|
||||||
case $TERM in
|
case $TERM in
|
||||||
*term | rxvt )
|
*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 )
|
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
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +192,7 @@ alias rm='rm -i'
|
||||||
alias cp='cp -i'
|
alias cp='cp -i'
|
||||||
alias mv='mv -i'
|
alias mv='mv -i'
|
||||||
# -> Prevents accidentally clobbering files.
|
# -> Prevents accidentally clobbering files.
|
||||||
|
alias mkdir='mkdir -p'
|
||||||
|
|
||||||
alias h='history'
|
alias h='history'
|
||||||
alias j='jobs -l'
|
alias j='jobs -l'
|
||||||
|
@ -151,23 +200,23 @@ alias r='rlogin'
|
||||||
alias which='type -all'
|
alias which='type -all'
|
||||||
alias ..='cd ..'
|
alias ..='cd ..'
|
||||||
alias path='echo -e ${PATH//:/\\n}'
|
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 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 background='xv -root -quit -max -rmode 5' # Put a picture in the background
|
||||||
alias vi='vim'
|
alias du='du -kh'
|
||||||
alias du='du -h'
|
alias df='df -kTh'
|
||||||
alias df='df -kh'
|
|
||||||
|
|
||||||
# The 'ls' family (this assumes you use the GNU ls)
|
# 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 ls='ls -hF --color' # add colors for filetype recognition
|
||||||
alias lx='ls -lXB' # sort by extension
|
alias lx='ls -lXB' # sort by extension
|
||||||
alias lk='ls -lSr' # sort by size
|
alias lk='ls -lSr' # sort by size
|
||||||
alias la='ls -Al' # show hidden files
|
alias lc='ls -lcr' # sort by change time
|
||||||
alias lr='ls -lR' # recursice ls
|
alias lu='ls -lur' # sort by access time
|
||||||
alias lt='ls -ltr' # sort by date
|
alias lr='ls -lR' # recursive ls
|
||||||
alias lm='ls -al |more' # pipe through 'more'
|
alias lt='ls -ltr' # sort by date
|
||||||
alias tree='tree -Cs' # nice alternative to 'ls'
|
alias lm='ls -al |more' # pipe through 'more'
|
||||||
|
alias tree='tree -Csu' # nice alternative to 'ls'
|
||||||
|
|
||||||
# tailoring 'less'
|
# tailoring 'less'
|
||||||
alias more='less'
|
alias more='less'
|
||||||
|
@ -190,10 +239,11 @@ alias kk='ll'
|
||||||
|
|
||||||
function xtitle ()
|
function xtitle ()
|
||||||
{
|
{
|
||||||
case $TERM in
|
case "$TERM" in
|
||||||
*term | rxvt)
|
*term | rxvt)
|
||||||
echo -n -e "\033]0;$*\007" ;;
|
echo -n -e "\033]0;$*\007" ;;
|
||||||
*) ;;
|
*)
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,21 +252,22 @@ alias top='xtitle Processes on $HOST && top'
|
||||||
alias make='xtitle Making $(basename $PWD) ; make'
|
alias make='xtitle Making $(basename $PWD) ; make'
|
||||||
alias ncftp="xtitle ncFTP ; ncftp"
|
alias ncftp="xtitle ncFTP ; ncftp"
|
||||||
|
|
||||||
# .. and functions
|
# .. and functions
|
||||||
function man ()
|
function man ()
|
||||||
{
|
{
|
||||||
xtitle The $(basename $1|tr -d .[:digit:]) manual
|
for i ; do
|
||||||
man -a "$*"
|
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 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
|
function te() # wrapper around xemacs/gnuserv
|
||||||
{
|
{
|
||||||
if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then
|
if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then
|
||||||
gnuclient -q "$@";
|
gnuclient -q "$@";
|
||||||
else
|
else
|
||||||
( xemacs "$@" & );
|
( xemacs "$@" &);
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,18 +275,33 @@ function te() # wrapper around xemacs/gnuserv
|
||||||
# File & strings related functions:
|
# File & strings related functions:
|
||||||
#-----------------------------------
|
#-----------------------------------
|
||||||
|
|
||||||
function ff() { find . -name '*'$1'*' ; } # find a file
|
# Find a file with a pattern in name:
|
||||||
function fe() { find . -name '*'$1'*' -exec $2 {} \; ; } # find a file and run $2 on it
|
function ff() { find . -type f -iname '*'$*'*' -ls ; }
|
||||||
function fstr() # find a string in a set of files
|
# 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
|
OPTIND=1
|
||||||
echo "Usage: fstr \"pattern\" [files] "
|
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;
|
return;
|
||||||
fi
|
fi
|
||||||
SMSO=$(tput smso)
|
local SMSO=$(tput smso)
|
||||||
RMSO=$(tput rmso)
|
local RMSO=$(tput rmso)
|
||||||
find . -type f -name "${2:-*}" -print | xargs grep -sin "$1" | \
|
find . -type f -name "${2:-*}" -print0 | xargs -0 grep -sn ${case} "$1" 2>&- | \
|
||||||
sed "s/$1/$SMSO$1$RMSO/gI"
|
sed "s/$1/${SMSO}\0${RMSO}/gI" | more
|
||||||
}
|
}
|
||||||
|
|
||||||
function cuttail() # cut last n lines in file, 10 by default
|
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
|
function swap() # swap 2 filenames around
|
||||||
{
|
{
|
||||||
local TMPFILE=tmp.$$
|
local TMPFILE=tmp.$$
|
||||||
mv $1 $TMPFILE
|
mv "$1" $TMPFILE
|
||||||
mv $2 $1
|
mv "$2" "$1"
|
||||||
mv $TMPFILE $2
|
mv $TMPFILE "$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#-----------------------------------
|
#-----------------------------------
|
||||||
# Process/system related functions:
|
# 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
|
function killps() # kill by process name
|
||||||
{
|
{
|
||||||
local pid pname sig="-TERM" # default signal
|
local pid pname sig="-TERM" # default signal
|
||||||
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
|
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
|
||||||
echo "Usage: killps [-SIGNAL] pattern"
|
echo "Usage: killps [-SIGNAL] pattern"
|
||||||
return;
|
return;
|
||||||
fi
|
fi
|
||||||
if [ $# = 2 ]; then sig=$1 ; fi
|
if [ $# = 2 ]; then sig=$1 ; fi
|
||||||
for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) ; do
|
for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) ; do
|
||||||
pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
|
pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
|
||||||
if ask "Kill process $pid <$pname> with signal $sig?"
|
if ask "Kill process $pid <$pname> with signal $sig?"
|
||||||
then kill $sig $pid
|
then kill $sig $pid
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +383,6 @@ function ii() # get current host related info
|
||||||
echo
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Misc utilities:
|
# Misc utilities:
|
||||||
|
|
||||||
function repeat() # repeat n times command
|
function repeat() # repeat n times command
|
||||||
|
@ -328,7 +394,6 @@ function repeat() # repeat n times command
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ask()
|
function ask()
|
||||||
{
|
{
|
||||||
echo -n "$@" '[y/n] ' ; read ans
|
echo -n "$@" '[y/n] ' ; read ans
|
||||||
|
@ -341,8 +406,9 @@ function ask()
|
||||||
#=========================================================================
|
#=========================================================================
|
||||||
#
|
#
|
||||||
# PROGRAMMABLE COMPLETION - ONLY SINCE BASH-2.04
|
# PROGRAMMABLE COMPLETION - ONLY SINCE BASH-2.04
|
||||||
# (Most are taken from the bash 2.05 documentation)
|
# Most are taken from the bash 2.05 documentation and from Ian McDonalds
|
||||||
# You will in fact need bash-2.05 for some features
|
# '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
|
fi
|
||||||
|
|
||||||
shopt -s extglob # necessary
|
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 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 export printenv
|
||||||
complete -A variable export local readonly unset
|
complete -A variable export local readonly unset
|
||||||
complete -A enabled builtin
|
complete -A enabled builtin
|
||||||
|
@ -372,40 +436,57 @@ complete -A job -P '%' fg jobs disown
|
||||||
complete -A directory mkdir rmdir
|
complete -A directory mkdir rmdir
|
||||||
complete -A directory -o default cd
|
complete -A directory -o default cd
|
||||||
|
|
||||||
complete -f -d -X '*.gz' gzip
|
# Compression
|
||||||
complete -f -d -X '*.bz2' bzip2
|
complete -f -o default -X '*.+(zip|ZIP)' zip
|
||||||
complete -f -o default -X '!*.gz' gunzip
|
complete -f -o default -X '!*.+(zip|ZIP)' unzip
|
||||||
complete -f -o default -X '!*.bz2' bunzip2
|
complete -f -o default -X '*.+(z|Z)' compress
|
||||||
complete -f -o default -X '!*.pl' perl perl5
|
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 '!*.ps' gs ghostview ps2pdf ps2ascii
|
||||||
complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype
|
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' acroread pdf2ps
|
||||||
complete -f -o default -X '!*.+(pdf|ps)' gv
|
complete -f -o default -X '!*.+(pdf|ps)' gv
|
||||||
complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
|
complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
|
||||||
complete -f -o default -X '!*.tex' tex latex slitex
|
complete -f -o default -X '!*.tex' tex latex slitex
|
||||||
complete -f -o default -X '!*.lyx' lyx
|
complete -f -o default -X '!*.lyx' lyx
|
||||||
complete -f -o default -X '!*.+(jpg|gif|xpm|png|bmp)' xv gimp
|
complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps
|
||||||
complete -f -o default -X '!*.mp3' mpg123
|
# Multimedia
|
||||||
complete -f -o default -X '!*.ogg' ogg123
|
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
|
# This is a 'universal' completion function - it works when commands have
|
||||||
# a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
|
# a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
|
||||||
_universal_func ()
|
|
||||||
|
_get_longopts ()
|
||||||
|
{
|
||||||
|
$1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \
|
||||||
|
grep ^"$2" |sort -u ;
|
||||||
|
}
|
||||||
|
|
||||||
|
_longopts_func ()
|
||||||
{
|
{
|
||||||
case "$2" in
|
case "${2:-*}" in
|
||||||
-*) ;;
|
-*) ;;
|
||||||
*) return ;;
|
*) return ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
\~*) eval cmd=$1 ;;
|
\~*) eval cmd="$1" ;;
|
||||||
*) cmd="$1" ;;
|
*) cmd="$1" ;;
|
||||||
esac
|
esac
|
||||||
COMPREPLY=( $("$cmd" --help | sed -e '/--/!d' -e 's/.*--\([^ ]*\).*/--\1/'| \
|
COMPREPLY=( $(_get_longopts ${1} ${2} ) )
|
||||||
grep ^"$2" |sort -u) )
|
|
||||||
}
|
}
|
||||||
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 ()
|
_make_targets ()
|
||||||
|
@ -459,22 +540,6 @@ _make_targets ()
|
||||||
|
|
||||||
complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake
|
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(1) completion
|
||||||
_cvs ()
|
_cvs ()
|
||||||
|
@ -485,17 +550,16 @@ _cvs ()
|
||||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||||
|
|
||||||
if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
|
if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
|
||||||
COMPREPLY=( $( compgen -W 'add admin checkout commit diff \
|
COMPREPLY=( $( compgen -W 'add admin checkout commit diff \
|
||||||
export history import log rdiff release remove rtag status \
|
export history import log rdiff release remove rtag status \
|
||||||
tag update' $cur ))
|
tag update' $cur ))
|
||||||
else
|
else
|
||||||
COMPREPLY=( $( compgen -f $cur ))
|
COMPREPLY=( $( compgen -f $cur ))
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
complete -F _cvs cvs
|
complete -F _cvs cvs
|
||||||
|
|
||||||
|
|
||||||
_killall ()
|
_killall ()
|
||||||
{
|
{
|
||||||
local cur prev
|
local cur prev
|
||||||
|
@ -514,6 +578,60 @@ _killall ()
|
||||||
|
|
||||||
complete -F _killall killall killps
|
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 <function>
|
||||||
|
#
|
||||||
|
# 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 <type>
|
||||||
|
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:
|
# Local Variables:
|
||||||
# mode:shell-script
|
# mode:shell-script
|
||||||
# sh-shell:bash
|
# sh-shell:bash
|
||||||
|
|
|
@ -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,
|
# For an in-depth analysis on the topic of file deletion and security,
|
||||||
#+ see Peter Gutmann's paper,
|
#+ see Peter Gutmann's paper,
|
||||||
#+ "Secure Deletion of Data From Magnetic and Solid-State Memory".
|
#+ "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
|
exit 0
|
||||||
|
|
|
@ -24,10 +24,16 @@ do
|
||||||
filename=${file%.*c} # Strip ".mac" suffix off filename
|
filename=${file%.*c} # Strip ".mac" suffix off filename
|
||||||
#+ ('.*c' matches everything
|
#+ ('.*c' matches everything
|
||||||
#+ between '.' and 'c', inclusive).
|
#+ between '.' and 'c', inclusive).
|
||||||
$OPERATION $file > $filename.$SUFFIX
|
$OPERATION $file > "$filename.$SUFFIX"
|
||||||
# Redirect conversion to new filename.
|
# Redirect conversion to new filename.
|
||||||
rm -f $file # Delete original files after converting.
|
rm -f $file # Delete original files after converting.
|
||||||
echo "$filename.$SUFFIX" # Log what is happening to stdout.
|
echo "$filename.$SUFFIX" # Log what is happening to stdout.
|
||||||
done
|
done
|
||||||
|
|
||||||
exit 0
|
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.
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# empty-array.sh
|
# 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.
|
# An empty array is not the same as an array with empty elements.
|
||||||
|
|
||||||
array0=( first second third )
|
array0=( first second third )
|
||||||
|
@ -8,7 +12,9 @@ array1=( '' ) # "array1" has one empty element.
|
||||||
array2=( ) # No elements... "array2" is empty.
|
array2=( ) # No elements... "array2" is empty.
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
ListArray()
|
||||||
|
{
|
||||||
|
echo
|
||||||
echo "Elements in array0: ${array0[@]}"
|
echo "Elements in array0: ${array0[@]}"
|
||||||
echo "Elements in array1: ${array1[@]}"
|
echo "Elements in array1: ${array1[@]}"
|
||||||
echo "Elements in array2: ${array2[@]}"
|
echo "Elements in array2: ${array2[@]}"
|
||||||
|
@ -20,7 +26,101 @@ echo
|
||||||
echo "Number of elements in array0 = ${#array0[*]}" # 3
|
echo "Number of elements in array0 = ${#array0[*]}" # 3
|
||||||
echo "Number of elements in array1 = ${#array1[*]}" # 1 (surprise!)
|
echo "Number of elements in array1 = ${#array1[*]}" # 1 (surprise!)
|
||||||
echo "Number of elements in array2 = ${#array2[*]}" # 0
|
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
|
||||||
|
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
|
||||||
|
|
|
@ -17,3 +17,9 @@ echo >>logfile
|
||||||
echo >>logfile
|
echo >>logfile
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
# Exercise:
|
||||||
|
# --------
|
||||||
|
# Modify this script to track changes in /var/log/messages at intervals
|
||||||
|
#+ of 20 minutes.
|
||||||
|
# Hint: Use the "watch" command.
|
||||||
|
|
|
@ -7,7 +7,7 @@ DOC_REQUEST=70
|
||||||
if [ "$1" = "-h" -o "$1" = "--help" ] # Request help.
|
if [ "$1" = "-h" -o "$1" = "--help" ] # Request help.
|
||||||
then
|
then
|
||||||
echo; echo "Usage: $0 [directory-name]"; echo
|
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
|
sed -e '/DOCUMENTATIONXX/d'; exit $DOC_REQUEST; fi
|
||||||
|
|
||||||
: << DOCUMENTATIONXX
|
: << DOCUMENTATIONXX
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# @(#) tree 1.1 30/11/95 by Jordi Sanfeliu
|
# @(#) tree 1.1 30/11/95 by Jordi Sanfeliu
|
||||||
# email: mikaku@arrakis.es
|
# email: mikaku@fiwix.org
|
||||||
#
|
#
|
||||||
# Initial version: 1.0 30/11/95
|
# Initial version: 1.0 30/11/95
|
||||||
# Next version : 1.1 24/02/97 Now, with symbolic links
|
# Next version : 1.1 24/02/97 Now, with symbolic links
|
||||||
|
|
Loading…
Reference in New Issue