Subject: Summary of a Bash Lecture

From: Shlomi Fish <[email-masked]>
Date: Tue, 31 Oct 2000 08:24:17 +0200 (IST)

I'm considering giving a lecture about Bash to the Haifa Linux Club. I
started to write a summary of it and you can find it at the following URL:

http://vipe.technion.ac.il/~shlomif/lecture/Bash/

If you wish, read it and send your comments, either personally to me or to
the list.

Regards,

	Shlomi Fish

----------------------------------------------------------------------
Shlomi Fish        [email-masked] 
Home Page:         http://t2.technion.ac.il/~shlomif/
Home E-mail:       [email-masked]

The prefix "God Said" has the extraordinary logical property of 
converting any statement that follows it into a true one.

---

From: Omer Mussaev <[email-masked]>
Date: Tue, 31 Oct 2000 11:40:07 +0300

> If you wish, read it and send your comments, either personally to me or to

Why not do it collectively?

Original summary:

> Summary of sh/Bash Lecture:
> ------------------------
> 
> - Executing simple commands: command name followed by parameters
>    Examples:
>        ls
>        ls -l
>        cp test.pl old_test.pl
> 
> - Filename Matching mechanisms:
>    *
>    []
>    ?
>    Examples:
>        ls -l *.c
>        cp *.c ./bak_dir

simple readline quickies:

arrows - history
^-r  find command in history by name

readline is NOT shell

>       
> - Pipeline: explain a little about standard input/standard output, 
> then show
>    the following redirection mechanisms:
>    |
>    >
>    <
>    Examples:
>        ls -l | less
>        cat *.c *h | wc -l
>        ls -l | grep ^d | wc -l

What about :
   
    ls ./no_such_file 2>/dev/null
    FDT
    ls -l /proc/$$/fd/   to show file descriptors

> 
> - The ";" - executing more than one statements in the same batch. A
>    synchronous executions.
>    Examples:
>        cd ./test_dir ; tar -czvf ../test_dir.tar.gz *
>    

&&  - conditional execution

The following section is better be given after variables (IMHO)

> 
> - The "(" .. ")" - grouping statements inside a _subshell_ (separate 
> process).
>    Examples:
>        (cd ./bin ; ls d* ) > files_in_bin_that_start_with_a_d.txt

{}  - same process

put {} and give it a name - function.

Differences:  exported variables vs non-exported variables.

A=1
B=2
export A
{
  echo A is ${A:-"unset"}
  echo B is ${B:-"unset"}
}
(
  echo A is ${A:-"unset"}
  echo B is ${B:-"unset"}
)

Control structures:

do ; done - a block

if ; then ; fi
while
for atom in lat

> 
> - Using the backslash (with no whitespace afterwards) to split 
> commands across
>   several lines. Eases readability:
>    Examples:
>        cp *.c *.h README Makefile TODO \
>            USAGE INSTALL \
>                ./bak
> 
> - Introducing comments with "#". They start with a # and extend to the 
> end of
>   the line.
>  
> Variables:
> ----------
> 
> - Simple assignment: "=". (note that there cannot be any whitespace before
> and after the "=" symbol.)
>    Examples:
>    A=hello
>    B=yellow ; turn=500
> 
> - Retrieving the value of a variable using $ or ${} . (not $() !)
>    Examples:
>        - A=hello
>          echo $A
>        - VARIABLE=5
>          B=${VARIABLE}
>          VARIABLE=800
>          echo $B
>        - A=Y
>          Y=80
>          echo ${$A}
>         
> - A little about extrapolation: A dollar can appear anywhere. If the shell
>   encounters a $ which is not followed by curly brackets ("{" .. "}") 
> it will
>   try to extroplate its name from as many characters as it find, even if
>   a variable by that name does not exist. Thus, when in doubt, use the
>   "${NAME}" form.
> 
>    Examples:
>        - A=hello
>          echo $Aworld
>          # does not print helloworld
>   
> 
> - The "${parameter:-defaultvalue}" form enables you to give the 
> expression a
>   default value in case the variable is not assigned.
>    Examples:
>        -
>            #!/bin/bash
>           
>            ;
>            ; Possibly set A
>            B=${A:-not_set}
>            ; Check if B is equal to not_set and accordingly do something.
>           
> - To unset a variable use the "unset" command:
>    Examples:
>        -
>            #!/bin/bash
>            A=5
>            B=80
>            RESULT=400
>            echo $A \* $B = $RESULT
>            unset A B RESULT
> 
> - To display a list of the declared variables and their values, use 
> the "set"
>   command without any options. (set is of little use in scripts except for
>   debugging purposes).
> 
>   Examples:
>     -
>        A=32482 ; B=932840 ; C=1932840 ; D=890 ; E=hello ; F=world
>        unset A E
>        set | grep '^[A-F]='
> 
> - The "read VARNAME" command reads a line from the standard output and 
> puts
>   it inside the variable "VARNAME".
>    - Note: Do not use "read $VARNAME"!

Actualy, read $VARNAME is legal...

>   Examples:

`` and $() program substitution.
Why it is better to use $()
Example:
$( cd  $( echo "/usr" ) && pwd )  instead of
`cd \`echo "/usr"\' && pwd`

> To unsubscribe from this group, send an email to:
> [email-masked]
> 
>

---

From: Shlomi Fish <[email-masked]>
Date: Wed, 1 Nov 2000 14:46:56 +0200 (IST)

> ^-r  find command in history by name

I'm not planning to cover readline too much in the lecture, because:
1. It has lots of options, most of which I never use.
2. Most users are familiar with its basic options (tab, up and down
arrows, etc.)
3. I want my lecture to be as sh (ash) complaint as possible and the use
of readline is unique to bash and zsh.
 
>     ls -l /proc/$$/fd/   to show file descriptors

I plan to cover 2> 2>&1, etc. later on.

> >        (cd ./bin ; ls d* ) > files_in_bin_that_start_with_a_d.txt

Interesting, I did not know that, as I use ( .. ) most of the time.

> Differences:  exported variables vs non-exported variables.

I'm not finished with the lecture summary. I am going to cover loops,
conditionals, etc. but later on.

> Actualy, read $VARNAME is legal...

I know, maybe I should show them this code:
A=B
B=A
read $A
echo A
echo B

to demonstrate what it does.

> `cd \`echo "/usr"\' && pwd`

Like I said I am going to cover it just later on. And I know $() is
usually better than ``.

Regards,

	Shlomi Fish

---

From: "Nadav Har'El" <[email-masked]>
Date: Wed, 1 Nov 2000 15:26:01 +0200

> of readline is unique to bash and zsh.

Just a small correction: readline is a GNU library which any interactive
program can use to support line editing and history. Bash uses it, and
gnuplot and bc use it, for example. But neither zsh nor ksh use this library,
and instead use their own implementations (zsh's is called ZLE, the Zsh
Line Editor), so what you explain about readline doesn't directly apply
to zsh or ksh.
You're right that most people will guess the arrow keys (this works on bash and
zsh, but not on ksh which has VI bindings by default), but perhaps tab
completion isn't natural to someone who hasn't used such a shell before.

A propos readline, I once found a program (I still have its source code
lying around) called "ile" that added history to *any* interactive program
(without needed to recompile it). What it did is to define a new pseudo-
terminal, make the program you run output and input into this pty, and ile
controlled the master side adding support for line editing, history, and so
on. It worked very nicely: you could run 'ile cat' and get 'cat' with history
support :) A more realistic example is 'ile hoc' (hoc is a "high order
calculator" originally written by Brian Kernighan, which I enhanced since
1986).
I wonder why nobody wrote something like ile that uses readline, and why
such a thing doesn't come with popular Linux distributions (or maybe such
a thing exists, and I simply don't know about it).

> Interesting, I did not know that, as I use ( .. ) most of the time.

Maybe one of the suggestions to new users should be: read the manual :)
Both bash and zsh have excelent documents, and the "{...}" would be explained
in any shell book (even one from 20 years ago).

> >   echo B is ${B:-"unset"}

Hmm.. Did you actually try this? I don't think this would work like you
think - you won't get any "unset" error.. When the shell forks a subshell,
*all* its memory (including *all* variables, not only exported variables)
gets copied to the subshell.
Only when an external program is "execve"ed do the local variables get erased
from memory, and only the exported variables (the ones that are passed in
the 'environment' string of the process) survive.

> > > and after the "=" symbol.)

You should also explain the
	A=value command...
syntax, which is very very useful, and doesn't have a csh equivalent.
For example,
	DISPLAY=remotehost:0.0 xlogo

This syntax creates and exports a variable, but only for running one command
(it is returned to its previous state after running the command).

> to demonstrate what it does.

This discussion seems a bit exessive to me. Just say that "read A" is the
correct syntax... I mean, you also said that to assign a variable you do
A=3. What happens if somebody does $A=3? It's the same problem, and I see
no reason to talk about it much. That is, unless your listeners are Perl
experts, and are used to that $ everywhere :)

By the way, you fell into the same trap yourself - I think you meant "echo $A"
and "echo $B", not "echo A", "echo B"...

> Like I said I am going to cover it just later on. And I know $() is

I'm not sure "usually" is the correct word... For interactive use, the
backticks (grave accents) are easier because they're one less character to
type, and don't need to press the shift key. And they're the only command
substitution you had in the original Bourne Shell (not that this really
matters now... Even ash supports $(...) ).

-- 
Nadav Har'El                        |    Wednesday, Nov 1 2000, 3 Heshvan 5761
[email-masked]             |-----------------------------------------
Phone: +972-53-245868, ICQ 13349191 |(On the back of a VW Beetle) Don't honk,
http://nadav.harel.org.il           |I'm peddling as fast as I can.

---

From: Omer Mussaev <[email-masked]>
Date: Wed, 01 Nov 2000 19:58:25 +0300

> calculator" originally written by Brian Kernighan, which I enhanced since

Wow:)) thats very nice:)

> the 'environment' string of the process) survive.

Ooops.  My mistake.

> matters now... Even ash supports $(...) ).

Besides that,

eval may be intriguing and very useful

---

From: Shlomi Fish <[email-masked]>
Date: Wed, 1 Nov 2000 18:41:55 +0200 (IST)

> in any shell book (even one from 20 years ago).

Good point. I'll keep that in mind.

> and "echo $B", not "echo A", "echo B"...

You are right. It should be "echo $A" and "echo $B".
 
> matters now... Even ash supports $(...) ).

I'll tell users about both forms and explain the pros and cons of both.

	Shlomi Fish

---

From: Shlomi Fish <[email-masked]>
Date: Wed, 1 Nov 2000 18:48:27 +0200 (IST)

> eval may be intriguing and very useful

I am going to cover eval at a later stage. 

I once had to use it. I wanted to write a program that loads all the
modules my soundcard needed to operate, and I insisted on doing it using
insmod. I then wanted that when invoked as "/etc/rc.d/init.d/sound_modules
stop" it would remove them. My problem was that some of the module names
contained whitespace (because of the module parameters). So the only way I
found in order to process them in reverse topological order was to
use eval. I think I still have the script somewhere.

The moral of the story is: use modprobe!

Regards,

	Shlomi Fish

---

From: Adi Stav <[email-masked]>
Date: Wed, 1 Nov 2000 22:19:54 +0200

> If you wish, read it and send your comments, either personally to me or to

If you're mentioning ';', you might as well mention '&&' and '||'. 

[ conditions ] && command

is very useful and will be familiar to Perl people.

Also brace expansion, e.g. "ls -l {,/usr,/usr/X11R6}/bin/*sh" and why
is it different from filename expansion.

---

From: Moshe Zadka <[email-masked]>
Date: Thu, 2 Nov 2000 09:37:11 +0200 (IST)

> is very useful and will be familiar to Perl people.

Not to speak of the classical

make && run

idiom

--
Moshe Zadka <[email-masked]> -- 95855124
http://advogato.org/person/moshez

---

From: Shlomi Fish <[email-masked]>
Date: Thu, 2 Nov 2000 12:47:00 +0200 (IST)

> If you're mentioning ';', you might as well mention '&&' and '||'. 

I am, but I first have to explain about program return codes. And I
scheduled it for the chapter coming after quoting and backslashing.

Regards,

	Shlomi Fish