mirror of https://github.com/tLDP/LDP
Reworked several paragraphs. No new material. Still not ready for publication.
This commit is contained in:
parent
441c80818c
commit
c973d4cb22
|
@ -2,13 +2,13 @@
|
|||
|
||||
<!--
|
||||
IMPORTANT! Before doing any CVS commits, change the DTD from this:
|
||||
file:/cygdrive/c/franl/doc/docbook-xml-4.2-dtd/docbookx.dtd
|
||||
to this:
|
||||
http://docbook.org/xml/4.2/docbookx.dtd
|
||||
"file:/cygdrive/c/franl/doc/docbook-xml-4.2-dtd/docbookx.dtd"
|
||||
to:
|
||||
"http://docbook.org/xml/4.2/docbookx.dtd"
|
||||
-->
|
||||
|
||||
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://docbook.org/xml/4.2/docbookx.dtd"
|
||||
"http://docbook.org/xml/4.2/docbookx.dtd"
|
||||
[
|
||||
<!ENTITY ldp "Linux Documentation Project">
|
||||
<!ENTITY ldpurl "http://www.tldp.org/">
|
||||
|
@ -105,9 +105,9 @@
|
|||
The Bourne Again Shell (Bash) is the primary shell of the GNU system. It
|
||||
is compatible with the Bourne shell, which is one of the oldest UNIX
|
||||
shells, but it has many enhancements that make it superior to the Bourne
|
||||
shell for scripting. A Bash <firstterm>script</firstterm> is a
|
||||
human-readable file containing commands that are executed by Bash. This
|
||||
HOWTO is an introduction to writing Bash scripts.
|
||||
shell. A Bash <firstterm>script</firstterm> is a human-readable file
|
||||
containing commands that are executed by Bash. This HOWTO is an
|
||||
introduction to writing Bash scripts.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -159,7 +159,7 @@
|
|||
<title>Feedback</title>
|
||||
|
||||
<para>
|
||||
Feedback is welcome. Send your comments and/or criticisms to the author.
|
||||
Feedback is welcome. Send your comments to the author.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
|
@ -341,7 +341,7 @@ echo Hello world</programlisting>
|
|||
<para>
|
||||
Once you've created your <emphasis>Hello World</emphasis> script, you can
|
||||
execute it in a variety of ways. Let's assume that you named the script
|
||||
<filename>hello</filename> and it exists in your current working
|
||||
<filename>hello</filename>, and it exists in your current working
|
||||
directory. <xref linkend="ex-running-hello"/> shows how to execute the
|
||||
script. In this example, the interactive shell's prompt is shown as
|
||||
"<computeroutput>bash$</computeroutput>". Your shell's prompt might look
|
||||
|
@ -374,23 +374,25 @@ Hello world</screen>
|
|||
<para>
|
||||
The command "<computeroutput><command>bash
|
||||
hello</command></computeroutput>" starts a non-interactive Bash shell and
|
||||
passes it the name of the file containing the script to execute. While
|
||||
the script is running, there are actually <emphasis>two</emphasis>
|
||||
shells running! One is the interactive Bash shell which displays the
|
||||
"<computeroutput>bash$</computeroutput>" prompt and executes the command
|
||||
"<computeroutput><command>bash hello</command></computeroutput>". The
|
||||
other is the non-interactive Bash shell that you manually started to
|
||||
execute the script. In <xref linkend="ex-running-hello"/>, the
|
||||
interactive shell is Bash, but you don't have to use Bash as your
|
||||
interactive shell to run a Bash script. The command shown in <xref
|
||||
linkend="ex-running-hello"/> will work no matter which interactive shell
|
||||
you use.
|
||||
passes it one argument: the name of the file containing the script to
|
||||
execute. While the script is running, there are actually
|
||||
<emphasis>two</emphasis> shells running! One is the interactive Bash
|
||||
shell which displays the "<computeroutput>bash$</computeroutput>" prompt
|
||||
and executes the command "<computeroutput><command>bash
|
||||
hello</command></computeroutput>". The other is the non-interactive Bash
|
||||
shell that you manually started to execute the script. The interactive
|
||||
shell isn't doing anything while the script is running – it's merely
|
||||
waiting for the non-interactive shell to terminate. In <xref
|
||||
linkend="ex-running-hello"/>, the interactive shell is Bash, but you don't
|
||||
have to use Bash as your interactive shell to run a Bash script. The
|
||||
command shown in <xref linkend="ex-running-hello"/> will work no matter
|
||||
which interactive shell you use.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It's a bit of a hassle to run Bash scripts this way. It would be simpler
|
||||
if you could just type the name of your script without the leading
|
||||
"<computeroutput>bash</computeroutput>" and have the operating system
|
||||
"<computeroutput>bash</computeroutput>" to make the operating system
|
||||
automatically start a new Bash shell to execute your script. That way,
|
||||
the script can be run just like any other program, even programs written
|
||||
in so-called "real" programming languages, such as C or C++. To allow
|
||||
|
@ -407,7 +409,9 @@ Hello world</screen>
|
|||
You don't have to grant execute permission just to yourself. The
|
||||
command
|
||||
"<computeroutput><command>chmod ugo+x hello</command></computeroutput>"
|
||||
allows everyone to execute your script.
|
||||
allows everyone to execute your script. See the man page for the
|
||||
<computeroutput><command>chmod</command></computeroutput> command for
|
||||
more information.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
@ -430,9 +434,7 @@ Hello world</screen>
|
|||
<para>
|
||||
Create a directory named "<filename>bin</filename>" under your home
|
||||
directory. You can do this with the command
|
||||
"<computeroutput><command>mkdir $HOME/bin</command></computeroutput>"
|
||||
or
|
||||
"<computeroutput><command>cd; mkdir bin</command></computeroutput>".
|
||||
"<computeroutput><command>mkdir $HOME/bin</command></computeroutput>".
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
@ -446,12 +448,12 @@ Hello world</screen>
|
|||
|
||||
<listitem>
|
||||
<para>
|
||||
List the full pathname of that "<filename>bin</filename>" directory in
|
||||
the value of your <envar>PATH</envar> environment variable (We cover
|
||||
variables in more detail in <xref linkend="sect-variables"/>). You
|
||||
can do this by putting the following line into your interactive Bash
|
||||
startup script (which is the file <filename>.bashrc</filename> in your
|
||||
home directory):
|
||||
List the full pathname of that directory in the value of your
|
||||
<envar>PATH</envar> environment variable (We cover variables in more
|
||||
detail in <xref linkend="sect-variables"/>). You can do this by
|
||||
putting the following line into your interactive Bash startup script
|
||||
(which is the file <filename>.bashrc</filename> in your home
|
||||
directory):
|
||||
|
||||
<blockquote>
|
||||
<computeroutput>PATH="$HOME/bin:$PATH"</computeroutput>
|
||||
|
@ -489,8 +491,8 @@ bash$ <command>chmod u+x hello</command>
|
|||
bash$ <command>./hello</command>
|
||||
Hello world
|
||||
bash$ <command>mkdir $HOME/bin</command>
|
||||
bash$ <command>PATH="$HOME/bin:$PATH"</command>
|
||||
bash$ <command>mv hello $HOME/bin</command>
|
||||
bash$ <command>PATH="$HOME/bin:$PATH"</command>
|
||||
bash$ <command>hello</command>
|
||||
Hello world</screen>
|
||||
</example>
|
||||
|
@ -518,12 +520,12 @@ Hello world</screen>
|
|||
Let's understand how the script shown in <xref linkend="ex-hello-script"/>
|
||||
works. It's just two lines long, but both lines are significant. Neither
|
||||
line can be left out. The first line
|
||||
("<computeroutput>#!/bin/bash</computeroutput>") tells the operating
|
||||
system which shell to spawn to execute this script. Unlike programs
|
||||
written in compiled languages, such as C, Pascal, or C++, a Bash script is
|
||||
<firstterm>interpreted</firstterm>, which means that some other program (the
|
||||
<firstterm>interpreter</firstterm>) must read the script and execute the
|
||||
commands in the script. Bash is the interpreter for a Bash script. A
|
||||
(<computeroutput>#!/bin/bash</computeroutput>) tells the operating system
|
||||
which shell to spawn to execute this script. Unlike programs written in
|
||||
compiled languages, such as C, Pascal, or C++, a Bash script is
|
||||
<firstterm>interpreted</firstterm>, which means that some other program
|
||||
(the <firstterm>interpreter</firstterm>) must read the script and execute
|
||||
the commands in the script. Bash is the interpreter for a Bash script. A
|
||||
good analogy is to think of a chef cooking a meal by reading a recipe. In
|
||||
this case, your script is the recipe, and Bash is the chef.
|
||||
</para>
|
||||
|
@ -550,7 +552,7 @@ Hello world</screen>
|
|||
<computeroutput><command>echo</command></computeroutput> command is the
|
||||
general purpose mechanism for producing output. It simply outputs its
|
||||
arguments to the terminal on which the script is running. A single space
|
||||
is output betwen each argument.
|
||||
is output betwen each argument, and a newline character is appended.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -561,7 +563,7 @@ Hello world</screen>
|
|||
linkend="sect-interactive-vs-noninteractive"/> for a short list of
|
||||
exceptions to this rule). But what about that
|
||||
<emphasis>shebang</emphasis> line
|
||||
("<computeroutput>#!/bin/bash</computeroutput>")? What happens when Bash
|
||||
(<computeroutput>#!/bin/bash</computeroutput>)? What happens when Bash
|
||||
reads and executes that line?
|
||||
</para>
|
||||
|
||||
|
@ -569,7 +571,7 @@ Hello world</screen>
|
|||
The answer is: nothing. The text between a
|
||||
"<computeroutput>#</computeroutput>" character and the end of the same
|
||||
line is a <firstterm>comment</firstterm>. A comment is completely ignored
|
||||
by Bash. You should use comments to make your script readable by others
|
||||
by Bash. You should use comments to make your script more readable
|
||||
by including information that helps the reader understand your script.
|
||||
We cover comments in more detail in <xref linkend="sect-comments"/>.
|
||||
</para>
|
||||
|
@ -579,7 +581,8 @@ Hello world</screen>
|
|||
by Bash, why can't you leave it out? Although it is ignored by Bash, it
|
||||
is not ignored by the operating system, which uses the first line of the
|
||||
script to determine which shell to spawn to interpret the script. Thus,
|
||||
the first line of a Bash script cannot be omitted, even though it is
|
||||
the first line of the Bash script shown in <xref
|
||||
linkend="ex-hello-script"/> cannot be omitted, even though it is
|
||||
ignored by Bash.
|
||||
</para>
|
||||
|
||||
|
@ -624,11 +627,11 @@ Hello world</screen>
|
|||
<computeroutput><command>fg</command></computeroutput>, and
|
||||
<computeroutput><command>jobs</command></computeroutput> commands to
|
||||
examine and manipulate the background job. You also cannot use the
|
||||
"<computeroutput><command>kill %JOBID</command></computeroutput>" form of
|
||||
the <computeroutput><command>kill</command></computeroutput> command
|
||||
to kill background jobs. This is not a great loss, since the job
|
||||
control commands were designed for use in an interactive shell, and
|
||||
they don't make much sense in a script.
|
||||
"<computeroutput><command>kill %JOBID</command></computeroutput>" form
|
||||
of the <computeroutput><command>kill</command></computeroutput>
|
||||
command to kill background jobs. This is not a great loss, since the
|
||||
job control commands were designed for interactive use, and they don't
|
||||
make much sense in a script.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
@ -662,12 +665,12 @@ Hello world</screen>
|
|||
<para>
|
||||
A comment is any text following a "<computeroutput>#</computeroutput>"
|
||||
character on the same line, but the "<computeroutput>#</computeroutput>"
|
||||
character must be the first character in a word. A Bash script should
|
||||
contain comments. Comments are ignored by Bash, but they help the person
|
||||
who reads the script to understand it. <xref linkend="ex-comments"/>
|
||||
shows a script containing some comments. This is also the first script
|
||||
we've seen that contains blank lines. Bash ignores blank lines, so you
|
||||
can use them to make your script more readable.
|
||||
character must be the first character in a word. Comments are ignored by
|
||||
Bash, but they help the person who reads the script to understand it.
|
||||
<xref linkend="ex-comments"/> shows a script containing some comments.
|
||||
This is also the first script we've seen that contains blank lines. Bash
|
||||
ignores blank lines, so you can use them to make your script more
|
||||
readable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -722,8 +725,7 @@ Hello</screen>
|
|||
Professional software engineers know this is not true. Software is hard
|
||||
to understand if you are not the author. Even if you are the author, it
|
||||
can be hard to understand long afterwards, when it isn't fresh in your
|
||||
mind. Between 20% and 50% of the content of your scripts should be
|
||||
comments.
|
||||
mind. 20% to 50% of the lines in your scripts should be comments.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
@ -760,10 +762,10 @@ Hello</screen>
|
|||
|
||||
<para>
|
||||
The double quote (<computeroutput>"</computeroutput>) character is the
|
||||
simplest of the quoting characters. It is used to group space-separated
|
||||
words together so that Bash treats them as if they were one word. For
|
||||
instance, if you need to refer to a file that has spaces in its name, you
|
||||
can use double quotes, as follows:
|
||||
simplest of the quoting characters. It is most commonly used to group
|
||||
space-separated words together so that Bash treats them as if they were
|
||||
one word. For instance, if you need to refer to a file that has spaces in
|
||||
its name, you can use double quotes, as follows:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -775,12 +777,12 @@ cat "meeting agenda.txt"</programlisting>
|
|||
|
||||
<para>
|
||||
In the above command, the
|
||||
<computeroutput><command>cat</command></computeroutput> command will be
|
||||
passed a single filename. Had the double quotes been ommitted, the
|
||||
<computeroutput><command>cat</command></computeroutput> program will be
|
||||
passed a single filename, <computeroutput>meeting
|
||||
agenda.txt</computeroutput>. Had the double quotes been omitted, the
|
||||
<computeroutput><command>cat</command></computeroutput> command would have
|
||||
been passed two filenames, <filename>meeting</filename> and
|
||||
<filename>agenda.txt</filename>, which is not what the user intended.
|
||||
It's important to understand that the
|
||||
<filename>agenda.txt</filename>. It's important to understand that the
|
||||
<computeroutput><command>cat</command></computeroutput> program receives
|
||||
this single argument:
|
||||
</para>
|
||||
|
@ -793,10 +795,11 @@ cat "meeting agenda.txt"</programlisting>
|
|||
|
||||
<para>
|
||||
Notice that there are no double quotes in the argument that
|
||||
<computeroutput><command>cat</command></computeroutput> receives. Quote
|
||||
characters are shell metacharacters, which means they are removed by Bash
|
||||
before the command is executed. Even though metacharacters are removed,
|
||||
they are not ignored by Bash. In the above
|
||||
<computeroutput><command>cat</command></computeroutput> receives, but
|
||||
there are double quotes in the command. Quote characters are
|
||||
<firstterm>metacharacters</firstterm>, which means they are removed by
|
||||
Bash before the command is executed. Even though metacharacters are
|
||||
removed, they are not ignored by Bash. In the above
|
||||
<computeroutput><command>cat</command></computeroutput> command, the
|
||||
double quotes change how Bash passes the arguments to the program, even
|
||||
though the <computeroutput><command>cat</command></computeroutput> program
|
||||
|
@ -807,8 +810,8 @@ cat "meeting agenda.txt"</programlisting>
|
|||
Double quotes (and their cousins, single quotes and backquotes) must occur
|
||||
in pairs within a command. Unfortunately, if you accidentally use an odd
|
||||
number of double quotes in a command, Bash will not report an error. This
|
||||
is because you can use double quotes to group words that span a newline
|
||||
character. Try this command in your interactive shell:
|
||||
happens because you can use double quotes to group words that span a
|
||||
newline character. Try this command in your interactive shell:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -824,10 +827,10 @@ two lines"</programlisting>
|
|||
of that command, your interactive shell doesn't execute the command.
|
||||
Instead, it notices that you have not typed a closing double quote, and
|
||||
prompts you to continue entering the command. Only when a complete
|
||||
command (with a balanced set of double quotes) has been entered, will
|
||||
pressing the <keysym>ENTER</keysym> key execute the command. You can
|
||||
write the above command in a shell script too, and it will behave the same
|
||||
way.
|
||||
command – with a balanced set of double quotes – has been
|
||||
entered, will pressing the <keysym>ENTER</keysym> key execute the command.
|
||||
You can write the above command in a shell script too, and it will behave
|
||||
the same way.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -885,14 +888,15 @@ echo "*"</programlisting>
|
|||
<para>
|
||||
From now on, we'll use the more technical term
|
||||
<firstterm>escape</firstterm> instead of <firstterm>quote</firstterm> to
|
||||
refer to using a metacharacter that removes the special meaning of another
|
||||
metacharacter. Let's be clear about exactly what double quotes do.
|
||||
Double quotes escape the following Bash metacharacters.
|
||||
mean using one metacharacter to remove the special meaning of another
|
||||
metacharacter. Let's be clear exactly which metacharacters double quotes
|
||||
escape. Double quotes escape the following Bash metacharacters.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Wildcard characters: <computeroutput>* ? [...]</computeroutput>
|
||||
Wildcard characters: <computeroutput>* ?
|
||||
[</computeroutput>...<computeroutput>]</computeroutput>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
@ -904,7 +908,7 @@ echo "*"</programlisting>
|
|||
</listitem>
|
||||
|
||||
<listitem>
|
||||
Background job creation character: <computeroutput>&</computeroutput>
|
||||
The background job creation character: <computeroutput>&</computeroutput>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
@ -934,13 +938,13 @@ echo Now type "start-backup".</programlisting>
|
|||
</para>
|
||||
|
||||
<para>
|
||||
Try the above command in an interactive Bash shell. The double quotes
|
||||
do not appear, because Bash removes them before executing the
|
||||
Try the above command in an interactive Bash shell. The double quotes do
|
||||
not appear, because Bash removes them before executing the
|
||||
<computeroutput><command>echo</command></computeroutput> command.
|
||||
Instead, you must escape the double quotes. That is, you must make Bash
|
||||
treat the double quote characters as if they are ordinary characters and
|
||||
not metacharacters. You might think that you can use double quotes to
|
||||
escape the double quotes, but this doesn't work:
|
||||
not metacharacters. You cannot use double quotes to escape the double
|
||||
quotes, like this:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1199,25 +1203,22 @@ echo Hello world > xyz</programlisting>
|
|||
|
||||
<para>
|
||||
In this example, the "<computeroutput>></computeroutput>" is a
|
||||
<firstterm>metacharacter</firstterm>, which is a character that is not
|
||||
strictly part of the command to be executed but instead has special
|
||||
meaning to Bash. The metacharacter
|
||||
"<computeroutput>></computeroutput>" tells Bash to temporarilly
|
||||
redirect standard output of the current command from its current
|
||||
destination (the terminal) to the specified file for the duration of the
|
||||
command. You can specify any relative or absolute pathname after the
|
||||
"<computeroutput>></computeroutput>". In this example, the output of
|
||||
the "<computeroutput><command>echo Hello world</command></computeroutput>"
|
||||
command is redirected to the file <filename>xyz</filename> in the current
|
||||
working directory.
|
||||
metacharacter. The "<computeroutput>></computeroutput>" tells Bash to
|
||||
temporarilly redirect standard output of the current command from its
|
||||
current destination (the terminal) to the specified file for the duration
|
||||
of the command. You can specify any relative or absolute pathname after
|
||||
the "<computeroutput>></computeroutput>". In this example, the output
|
||||
of the "<computeroutput><command>echo Hello
|
||||
world</command></computeroutput>" command is redirected to the file
|
||||
<filename>xyz</filename> in the current working directory.
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<title>Warning!</title>
|
||||
|
||||
<para>
|
||||
If you redirect standard output to a file that already exists, it is
|
||||
overwritten, destroying the previous contents of the file! Always be
|
||||
If you redirect standard output to a file that already exists, the file
|
||||
is overwritten, destroying the previous contents of the file! Always be
|
||||
sure that you don't have any valuable data in the file that is going to
|
||||
be overwritten by redirection.
|
||||
</para>
|
||||
|
|
Loading…
Reference in New Issue