mirror of https://github.com/tLDP/LDP
Added section on comments. Started section on quotes. Still not ready to be
published.
This commit is contained in:
parent
07c456a5bf
commit
7b3c4ef3d4
|
@ -1,5 +1,12 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<!--
|
||||
Author's note to self: switch to this DTD before committing this file
|
||||
into CVS:
|
||||
|
||||
http://docbook.org/xml/4.1.2/docbookx.dtd
|
||||
-->
|
||||
|
||||
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||
"http://docbook.org/xml/4.1.2/docbookx.dtd" [
|
||||
<!ENTITY ldp "Linux Documentation Project">
|
||||
|
@ -228,16 +235,16 @@
|
|||
<title>What and Where is Bash?</title>
|
||||
|
||||
<para>
|
||||
Bash is a <emphasis>shell</emphasis>, which is a program that reads
|
||||
Bash is a <firstterm>shell</firstterm>, which is a program that reads
|
||||
commands and executes them. Sometimes, the commands that Bash reads come
|
||||
directly from the keyboard as you type them. When this happens, we say
|
||||
that Bash is an <emphasis>interactive</emphasis> shell. If you've ever
|
||||
that Bash is an <firstterm>interactive</firstterm> shell. If you've ever
|
||||
logged into a UNIX system, then you've probably used an interactive shell.
|
||||
Bash is the default interactive shell of the GNU/Linux system (and you
|
||||
might also find it installed on commercial UNIX systems). Sometimes, the
|
||||
commands that Bash reads come from a file called a <emphasis>shell
|
||||
script</emphasis>. When this happens, we say that Bash is a
|
||||
<emphasis>non-interactive</emphasis> shell. In this case, Bash reads each
|
||||
commands that Bash reads come from a file called a <firstterm>shell
|
||||
script</firstterm>. When this happens, we say that Bash is a
|
||||
<firstterm>non-interactive</firstterm> shell. In this case, Bash reads each
|
||||
line of the script file from top to bottom, executing each command as if
|
||||
it had been typed on the keyboard.
|
||||
</para>
|
||||
|
@ -247,7 +254,7 @@
|
|||
Bash in <filename>/bin/bash</filename>. On commerical UNIX systems, such
|
||||
as Solaris or HP-UX, you might find it in the same place, or it might be
|
||||
in <filename>/usr/local/bin/bash</filename>. You rarely need to run Bash
|
||||
directly, but you need to know where Bash is located on your system, so
|
||||
directly, but you need to know where Bash is located on your system so
|
||||
that you can write the very first line of your Bash scripts correctly.
|
||||
</para>
|
||||
|
||||
|
@ -282,7 +289,7 @@
|
|||
<para>
|
||||
Let's start with a simple Bash script and work up to more complex ones
|
||||
later. Just about the simplest program you can write in any programming
|
||||
language is a <emphasis>Hello world</emphasis> program, which is a program
|
||||
language is a <emphasis>Hello World</emphasis> program, which is a program
|
||||
that simply outputs the text "Hello world". <xref
|
||||
linkend="ex-hello-script"/> shows a Bash script to do that.
|
||||
</para>
|
||||
|
@ -290,7 +297,7 @@
|
|||
<para>
|
||||
<blockquote>
|
||||
<example id="ex-hello-script">
|
||||
<title>A Simple <emphasis>Hello world</emphasis> Script</title>
|
||||
<title>A Simple <emphasis>Hello World</emphasis> Script</title>
|
||||
<programlisting>
|
||||
#!/bin/bash
|
||||
echo Hello world</programlisting>
|
||||
|
@ -300,7 +307,7 @@ echo Hello world</programlisting>
|
|||
|
||||
<para>
|
||||
<xref linkend="ex-hello-script"/> shows a very simple two-line Bash script.
|
||||
Create this script by simply typing those two lines into a file using your
|
||||
Create this script by typing those two lines into a file using your
|
||||
favorite text editor. The name of the file can be anything you choose,
|
||||
but you should <emphasis>not</emphasis> name the file
|
||||
"<filename>test</filename>", because there is a built-in
|
||||
|
@ -327,7 +334,7 @@ echo Hello world</programlisting>
|
|||
<title>Running the <emphasis>Hello World</emphasis> Script</title>
|
||||
|
||||
<para>
|
||||
Once you've created your <emphasis>Hello world</emphasis> script, you can
|
||||
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
|
||||
directory. <xref linkend="ex-running-hello"/> shows how to execute the
|
||||
|
@ -360,13 +367,13 @@ Hello world</programlisting>
|
|||
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> Bash
|
||||
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 be using Bash as your
|
||||
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.
|
||||
|
@ -387,12 +394,12 @@ Hello world</programlisting>
|
|||
<listitem>
|
||||
<para>
|
||||
Change the permissions on the script to allow you to execute it. This
|
||||
can be done with the command "<computeroutput><command>chmod u+x
|
||||
hello</command></computeroutput>". 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.
|
||||
can be done with the command
|
||||
"<computeroutput><command>chmod u+x hello</command></computeroutput>".
|
||||
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.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
@ -413,18 +420,19 @@ Hello world</programlisting>
|
|||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Create a directory named "<filename>bin</filename>"
|
||||
under your home directory. You can do that with the command
|
||||
"<computeroutput><command>mkdir $HOME/bin</command></computeroutput>"
|
||||
or "<computeroutput><command>cd; mkdir bin</command></computeroutput>".
|
||||
Create a directory named "<filename>bin</filename>" under your home
|
||||
directory. You can do that with the command
|
||||
"<computeroutput><command>mkdir $HOME/bin</command></computeroutput>"
|
||||
or
|
||||
"<computeroutput><command>cd; mkdir bin</command></computeroutput>".
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Put the script in that directory. You can do that with the command
|
||||
"<computeroutput><command>mv hello $HOME/bin</command></computeroutput>"
|
||||
or "<computeroutput><command>mv hello ~/bin</command></computeroutput>".
|
||||
"<computeroutput><command>mv hello $HOME/bin</command></computeroutput>"
|
||||
or "<computeroutput><command>mv hello ~/bin</command></computeroutput>".
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
@ -439,6 +447,8 @@ Hello world</programlisting>
|
|||
<blockquote>
|
||||
<computeroutput>PATH="$HOME/bin:$PATH"</computeroutput>
|
||||
</blockquote>
|
||||
|
||||
We cover variables in more detail in <xref linkend="sect-variables"/>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
@ -504,8 +514,8 @@ Hello world</programlisting>
|
|||
("<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
|
||||
<emphasis>interpreted</emphasis>, which means that some other program (the
|
||||
<emphasis>interpreter</emphasis>) must read the script and execute the
|
||||
<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.
|
||||
|
@ -519,10 +529,9 @@ Hello world</programlisting>
|
|||
where it is installed and write the first line of your script accordingly.
|
||||
If you are using Linux, then Bash is always installed in
|
||||
<filename>/bin/bash</filename>. The first line in a shell script is
|
||||
sometimes called the <emphasis>shebang</emphasis> line. This term is
|
||||
sometimes called the <firstterm>shebang</firstterm> line. This term is
|
||||
derived from the use of the word "bang" to refer to an exclaimation mark
|
||||
and the fact that the first line of a shell script names a shell. It is
|
||||
also called the <emphasis>pound-bang</emphasis> line.
|
||||
and the fact that the first line of a shell script names a shell.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -552,9 +561,10 @@ Hello world</programlisting>
|
|||
<para>
|
||||
The answer is: nothing. The text between a
|
||||
"<computeroutput>#</computeroutput>" character and the end of the same
|
||||
line is a <emphasis>comment</emphasis>. A comment is completely ignored
|
||||
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 including information that helps the reader understand your script.
|
||||
We cover comments in more detail in <xref linkend="sect-comments"/>.
|
||||
Since the "<computeroutput>#!/bin/bash</computeroutput>" line is ignored
|
||||
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
|
||||
|
@ -641,17 +651,141 @@ Hello world</programlisting>
|
|||
<sect2 id="sect-comments">
|
||||
<title>Comments</title>
|
||||
|
||||
<para>*** UNDER CONSTRUCTION ***</para>
|
||||
<!--
|
||||
*************************************************************
|
||||
* UNDER CONSTRUCTION *
|
||||
*************************************************************
|
||||
-->
|
||||
A Bash script should contain comments. Comments are ignored by Bash, but
|
||||
they help the person who reads the script to understand it. A comment is any
|
||||
text following a "<computeroutput>#</computeroutput>" character on the
|
||||
same line. The "<computeroutput>#</computeroutput>" character must be the
|
||||
first character in a word. <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>
|
||||
<blockquote>
|
||||
<example id="ex-comments">
|
||||
<title>Using Comments</title>
|
||||
<programlisting>
|
||||
#!/bin/bash
|
||||
# This script is an example of using comments.
|
||||
echo Hello world # This comment shares a line with a command!
|
||||
|
||||
# The next line does _not_ contain a comment! Do you see why?
|
||||
echo Hello#world
|
||||
|
||||
# This is also a comment. The "#" doesn't have to be in the leftmost
|
||||
# column. Compare the next echo command with # the previous echo
|
||||
# command. One little space can make a big difference!
|
||||
echo Hello #world</programlisting>
|
||||
</example>
|
||||
</blockquote>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The first line in the script shown in <xref linkend="ex-comments"/> is the
|
||||
classic shebang line, described earlier. The comments should be fairly
|
||||
easy to see. The line that reads
|
||||
"<computeroutput>echo Hello#world</computeroutput>" also contains a
|
||||
"<computeroutput>#</computeroutput>" character, but there is
|
||||
<emphasis>no</emphasis> comment on that line, because the
|
||||
"<computeroutput>#</computeroutput>" does not occur at the beginning of a
|
||||
word. <xref linkend="ex-comments2"/> shows the output produced when this
|
||||
script is executes (assuming it is in a file named
|
||||
<filename>comments</filename>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<blockquote>
|
||||
<example id="ex-comments2">
|
||||
<title>Using Comments</title>
|
||||
<programlisting>
|
||||
bash$ <command>bash comments</command>
|
||||
Hello world
|
||||
Hello#world
|
||||
Hello</programlisting>
|
||||
</example>
|
||||
</blockquote>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Some people think that writing comments in a script or other kind of
|
||||
program is a waste of time. Professional software engineers know that is
|
||||
not true. Software -- and Bash scripts are definitely software -- is hard
|
||||
to understand if you didn't write it. Even if you wrote it, it can be
|
||||
hard to understand long afterwards, when it isn't fresh in your mind. You
|
||||
should aim to have between 20% and 50% of the content of your scripts be
|
||||
comments.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="sect-quotes">
|
||||
<title>Using Quotes</title>
|
||||
|
||||
<para>
|
||||
It is virtually impossible to write a Bash script without using quotes of
|
||||
one form or another. In a Bash script, the quote characters are:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<computeroutput>"</computeroutput> (double quote)
|
||||
</listitem>
|
||||
<listitem>
|
||||
<computeroutput>'</computeroutput> (single quote)
|
||||
</listitem>
|
||||
<listitem>
|
||||
<computeroutput>`</computeroutput> (backquote)
|
||||
</listitem>
|
||||
<listitem>
|
||||
<computeroutput>\</computeroutput> (backslash)
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
Let's look at each one in turn. The double quote
|
||||
(<computeroutput>"</computeroutput>) character is the simplest of the
|
||||
quoting characters. It is used to group multiple 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>
|
||||
|
||||
<blockquote>
|
||||
<para>
|
||||
<computeroutput>cat "meeting agenda.txt"</computeroutput>
|
||||
</para>
|
||||
</blockquote>
|
||||
|
||||
<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> command would have
|
||||
been passed two filenames, <filename>meeting</filename> and
|
||||
<filename>agenda.txt</filename>, neither of which exist. It's important
|
||||
to understand just what the
|
||||
<computeroutput><command>cat</command></computeroutput> program sees as
|
||||
its first argument when the above command executes. The
|
||||
<computeroutput><command>cat</command></computeroutput> program sees
|
||||
precisely this text as a single command-line argument:
|
||||
</para>
|
||||
|
||||
<blockquote>
|
||||
<para>
|
||||
<computeroutput>meeting agenda.txt</computeroutput>
|
||||
</para>
|
||||
</blockquote>
|
||||
|
||||
<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 definitely not ignored by Bash. In the above
|
||||
<computeroutput><command>cat</command></computeroutput> command, the
|
||||
double quotes changed how Bash passed the arguments to the program, even
|
||||
though the program never saw the double quotes!
|
||||
</para>
|
||||
|
||||
<para>*** UNDER CONSTRUCTION ***</para>
|
||||
<!--
|
||||
*************************************************************
|
||||
|
@ -677,7 +811,7 @@ Hello world</programlisting>
|
|||
|
||||
<para>
|
||||
It's almost impossible to write a non-trivial Bash script without using
|
||||
<emphasis>I/O redirection</emphasis>. Every UNIX shell, Bash included,
|
||||
<firstterm>I/O redirection</firstterm>. Every UNIX shell, Bash included,
|
||||
provides I/O redirection, but the syntax differs between various shells.
|
||||
Naturally, we'll cover the Bash syntax.
|
||||
</para>
|
||||
|
@ -686,15 +820,15 @@ Hello world</programlisting>
|
|||
<title>The Standard I/O Streams</title>
|
||||
|
||||
<para>
|
||||
A running program is called a <emphasis>process</emphasis>. When you type a
|
||||
A running program is called a <firstterm>process</firstterm>. When you type a
|
||||
command, such as "<computeroutput><command>ls</command></computeroutput>",
|
||||
Bash spawns a new process to execute the
|
||||
<computeroutput><command>ls</command></computeroutput> program. The new
|
||||
process exists only for the time it takes the
|
||||
"<computeroutput><command>ls</command></computeroutput>" command to execute,
|
||||
"<computeroutput><command>ls</command></computeroutput>" program to execute,
|
||||
and then the process terminates. When Bash starts a process to execute a
|
||||
command, the process is connected to several <emphasis>I/O
|
||||
streams</emphasis>. An I/O stream is like a hose that has one end
|
||||
command, the process is connected to several <firstterm>I/O
|
||||
streams</firstterm>. An I/O stream is like a hose that has one end
|
||||
connected to the process and the other end connected to a terminal. Data
|
||||
flows through an I/O stream like water flows through a hose. The data flows
|
||||
either from the process to the terminal (this is how the process produces
|
||||
|
@ -703,8 +837,8 @@ Hello world</programlisting>
|
|||
</para>
|
||||
|
||||
<para>
|
||||
When a process first starts, there are always three <emphasis>standard I/O
|
||||
streams</emphasis> connected to the process:
|
||||
When a process first starts, there are always three <firstterm>standard I/O
|
||||
streams</firstterm> connected to the process:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
@ -714,10 +848,10 @@ Hello world</programlisting>
|
|||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
<emphasis>Standard input</emphasis> is the name of the I/O stream through
|
||||
which a process reads input from its terminal. <emphasis>Standard
|
||||
output</emphasis> is the name of the I/O stream through which a process
|
||||
writes output to its terminal. <emphasis>Standard error</emphasis> is the
|
||||
<firstterm>Standard input</firstterm> is the name of the I/O stream through
|
||||
which a process reads input from its terminal. <firstterm>Standard
|
||||
output</firstterm> is the name of the I/O stream through which a process
|
||||
writes output to its terminal. <firstterm>Standard error</firstterm> is the
|
||||
name of the I/O stream through which a process writes error messages to
|
||||
its terminal. These standard I/O streams are sometimes referred to using
|
||||
their shorthand names: <firstterm>stdin</firstterm>,
|
||||
|
@ -725,17 +859,18 @@ Hello world</programlisting>
|
|||
</para>
|
||||
|
||||
<para>
|
||||
When your Bash script is running, it is a process just like any other, so it
|
||||
also has these three standard I/O streams. The
|
||||
<computeroutput><command>echo</command></computeroutput> command writes its
|
||||
output to standard output. Since standard output is connected by default to
|
||||
the terminal on which the script is running, the output of the
|
||||
<computeroutput><command>echo</command></computeroutput> typically appears
|
||||
on that terminal. But it is possible to <emphasis>redirect</emphasis> an
|
||||
I/O stream so that it is not connected to the terminal but to a file on
|
||||
disk. <xref linkend="ex-redirect-stdout"/> shows how to write an
|
||||
<computeroutput><command>echo</command></computeroutput> command that
|
||||
redirects standard output to a file.
|
||||
When your Bash script is running, it is a process just like any other, so
|
||||
it also has these three standard I/O streams. The
|
||||
<computeroutput><command>echo</command></computeroutput> command writes
|
||||
its output to standard output. Standard output is usually connected to
|
||||
the terminal on which the script is running, so the output of the
|
||||
<computeroutput><command>echo</command></computeroutput> command typically
|
||||
appears on that terminal. It is possible to
|
||||
<firstterm>redirect</firstterm> an I/O stream so that it is not connected
|
||||
to the terminal but to a file. <xref linkend="ex-redirect-stdout"/> shows
|
||||
show you can change the <filename>hello</filename> script to redirect the
|
||||
standard output of the echo command to a file named
|
||||
<filename>xyz</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -751,24 +886,28 @@ echo Hello world > xyz</programlisting>
|
|||
</para>
|
||||
|
||||
<para>
|
||||
In this example, the "<computeroutput>> xyz</computeroutput>" at the end of
|
||||
the "<computeroutput>echo Hello world</computeroutput>" command tells Bash
|
||||
to temporarilly redirect the script's standard output stream from its
|
||||
current destination (the terminal) to the file "<filename>xyz</filename>"
|
||||
for the duration of the
|
||||
<computeroutput><command>echo</command></computeroutput> command. You can
|
||||
specify any relative or absolute pathname after the
|
||||
"<computeroutput>></computeroutput>".
|
||||
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.
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<title>Warning!</title>
|
||||
|
||||
<para>
|
||||
If the file specified in the output redirection already exists, it 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 output redirection.
|
||||
If you redirect standard output to a file that already exists, it 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>
|
||||
</warning>
|
||||
|
||||
|
@ -859,7 +998,7 @@ echo Hello world > xyz</programlisting>
|
|||
<title>The <computeroutput>&&</computeroutput> Operator</title>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="sect-andand">
|
||||
<sect2 id="sect-oror">
|
||||
<title>The <computeroutput>||</computeroutput> Operator</title>
|
||||
</sect2>
|
||||
|
||||
|
|
Loading…
Reference in New Issue