<!--
     The FreeBSD Italian Documentation Project

     $FreeBSD: doc/it_IT.ISO8859-15/books/unix-introduction/shell-programming/chapter.sgml,v 1.1 2003/03/19 18:46:42 trhodes Exp $
-->

<chapter id="shell-programming">
  <title>Programmazione di shell</title>

  <sect1 id="shell-programming-scripts">
    <title>Script di shell</title>

    <para>Si possono scrivere programmi di shell creando script contenenti
      alcuni comandi di shell.  La prima linea dello script deve iniziare con
      #!, che indica al kernel che lo script &egrave; direttamente eseguibile.
      Si fa immediatamente seguire a quel simbolo il nome della shell
      o del programma da eseguire (gli spazi sono permessi), usando un path name
      assoluto.  Generalmente si possono avere fino a 32 caratteri, forse di
      pi&ugrave; su alcuni sistemi e si pu&ograve; includere qualche opzione.
      Quindi per inizializzare uno script per la shell Bourne la prima linea
      dovr&agrave; essere:</para>

    <programlisting>#! /bin/sh</programlisting>

    <para>e per la shell C:</para>

    <programlisting>#! /bin/csh -f</programlisting>

    <para>dove l'opzione <option>-f</option> indica che la shell non deve
      leggere il file <filename>.cshrc</filename>.  Alcuni spazi bianchi
      seguenti il magico simbolo, #!, sono opzionali.</para>

    <para>Inoltre si deve specificare che lo script &egrave; eseguibile,
      settando gli opportuni bit sul file con il comando &man.chmod.1;,
      esempio:</para>

    <screen>&prompt.user; <userinput>chmod +x <replaceable>shell_script</replaceable></userinput></screen>

    <para>All'interno degli script il simbolo # indica un commento da quel punto
      fino alle fine della linea; #! &egrave; un caso speciale se trovato come
      primo carattere del file.</para>
  </sect1>

  <sect1 id="shell-programming-sett-param-val">
    <title>Settare i valori dei parametri</title>

    <para>I valori di un parametro, ad esempio <literal>param</literal>, sono
      assegnati cos&igrave;:</para>

    <informaltable frame="none">
      <tgroup cols="2">
        <colspec colwidth="1.5in">

        <thead>
          <row>
            <entry>Shell Bourne</entry>

            <entry>Shell C</entry>
          </row>
        </thead>

        <tbody>
          <row>
            <entry><command>param=<replaceable>valore</replaceable></command></entry>

            <entry><command>set param =
                <replaceable>valore</replaceable></command></entry>
          </row>
        </tbody>
      </tgroup>
    </informaltable>

    <para>dove <replaceable>valore</replaceable> &egrave; una valida stringa che
      pu&ograve; essere chiusa tra caratteri di quoting singoli
      ('<replaceable>valore</replaceable>') o doppi
      ("<replaceable>valore</replaceable>") per permettere alcuni spazi bianchi
      all'interno del valore della stringa.  Quando viene racchiusa con dei
      caratteri backquote (`<replaceable>valore</replaceable>`) la stringa viene
      prima valutata dalla shell e viene sostituita con il risultato ottenuto
      dalla valutazione.  Questo viene spesso usato per eseguire un comando,
      sostituendo l'output del comando a <replaceable>valore</replaceable>,
      esempio:</para>

      <screen>$ <userinput>day=`date +%a`</userinput></screen>

      <screen>$ <userinput>echo $day</userinput>
Wed</screen>

    <para>Dopo che il valore del parametro &egrave; stato assegnato, si accede
      al valore corrente del parametro usando la notazione
      <literal>$param</literal> o <literal>${param}</literal>.</para>
  </sect1>

  <sect1 id="shell-programming-quoting">
    <title>Quoting</title>

    <para>Le stringhe possono essere quotate per controllare il modo in cui la
      shell interpreta alcuni parametri o variabili all'interno della stringa.
      Per delimitare le stringhe si possono usare i caratteri di quoting singoli
      (') o doppi (").  I caratteri di quoting doppi definiscono la stringa e
      permettono la sostituzione di variabile.  I carattere di quoting singoli
      definiscono la stringa ma impediscono la sostituzione di variabile.
      Un backslash (\) prima di un carattere viene posto per effettuare un
      escape su di esso, specificando che il sistema deve considerare il
      carattere letteralmente, senza assegnarli alcun significato speciale.
      Queste tecniche di quoting possono essere usate per separare una variabile
      da una stringa fissa.  Come esempio si consideri la variabile
      <literal>var</literal>, a cui &egrave; stata assegnata il valore
      <literal>bat</literal>, e la stringa costante <literal>man</literal>.  Se
      si vuole combinare queste stringhe per ottenere come risultato la stringa
      <literal>batman</literal> si pu&ograve; sperimentare:</para>

    <para><literal>$varman</literal></para>

    <para>ma questo non funzioner&agrave;, poich&egrave; la shell tenta di
      valutare una variabile chiamata <literal>varman</literal>, che non esiste.
      Per ottenere il risultato desiderato si ha la necessit&agrave; di separare
      le stringhe tramite quoting o di isolare la variabile con delle parentesi
      graffe ({}), in questo modo:</para>

    <informaltable frame="none">
      <tgroup cols="2">
        <colspec colwidth="1.5in">

        <tbody>
          <row>
            <entry><literal>"$var"man</literal></entry>

            <entry>- quoting sulla variabile</entry>
          </row>

          <row>
            <entry><literal>$var""man</literal></entry>

            <entry>- separazione di parametri</entry>
          </row>

          <row>
            <entry><literal>$var"man"</literal></entry>

            <entry>- quoting sulla costante</entry>
          </row>

          <row>
            <entry><literal>$var''man</literal></entry>

            <entry>- separazione di parametri</entry>
          </row>

          <row>
            <entry><literal>$var'man'</literal></entry>

            <entry>- quoting sulla costante</entry>
          </row>

          <row>
            <entry><literal>$var\man</literal></entry>

            <entry>- separazione di parametri</entry>
          </row>

          <row>
            <entry><literal>${var}man</literal></entry>

            <entry>- si isola la variabile</entry>
          </row>
        </tbody>
      </tgroup>
    </informaltable>

    <para>Queste funzionano tutte poich&egrave; ", ', \, { e } non sono validi
      caratteri per un nome di variabile.</para>

    <para>Non si pu&ograve; usare</para>

    <para><literal>'$var'man</literal></para>

    <para><literal>\$varman</literal></para>

    <para>poich&egrave; impediscono che la sostituzione della variabile
      prenda posto.</para>

    <para>Quando si usano le parentesi graffe, queste devono circondare
      solamente la variabile, senza includere il $, altrimenti saranno incluse
      come parte del risultato della stringa, esempio:</para>

    <screen>&prompt.user; <userinput>echo {$var}man</userinput>
{bat}man</screen>
  </sect1>

  <sect1 id="shell-programming-var">
    <title>Variabili</title>

    <para>Alcune variabili sono automaticamente inizializzate all'avvio della
      shell.  Queste variabili permettono di riferirsi agli argomenti su linea
      di comando.</para>

    <para>Queste <emphasis>variabili di shell</emphasis> sono:</para>

    <table frame=all id="shell-programming-table-shell-var">
      <title>Variabili di shell</title>

      <tgroup cols="4">
        <colspec colwidth="1in">

        <colspec colwidth="5in">

        <colspec colwidth="0.3in">

        <colspec colwidth="0.3in">

        <thead>
          <row>
            <entry align="center">Variabile</entry>

            <entry align="center">Uso</entry>

            <entry align="center">sh</entry>

            <entry align="center">csh</entry>
          </row>
        </thead>

        <tbody>
          <row>
            <entry><literal>$#</literal></entry>

            <entry>numero di argomenti su linea di comando</entry>

            <entry align="center">x</entry>

            <entry align="center"></entry>
          </row>

          <row>
            <entry><literal>$-</literal></entry>

            <entry>opzioni fornite alla shell</entry>

            <entry align="center">x</entry>

            <entry align="center"></entry>
          </row>

          <row>
            <entry><literal>$?</literal></entry>

            <entry>valore di uscita dell'ultimo comando eseguito</entry>

            <entry align="center">x</entry>

            <entry align="center"></entry>
          </row>

          <row>
            <entry><literal>$$</literal></entry>

            <entry>numero id del processo corrente</entry>

            <entry align="center">x</entry>

            <entry align="center">x</entry>
          </row>

          <row>
            <entry><literal>$!</literal></entry>

            <entry>numero di processo dell'ultimo comando messo in
              background</entry>

            <entry align="center">x</entry>

            <entry align="center"></entry>
          </row>

          <row>
            <entry><literal>$<replaceable>n</replaceable></literal></entry>

            <entry>argomento su linea di comando, dove
              <replaceable>n</replaceable> varia tra 1 e 9, leggendo da sinistra
              a destra</entry>

            <entry align="center">x</entry>

            <entry align="center">x</entry>
          </row>

          <row>
            <entry><literal>$0</literal></entry>

            <entry>il nome della shell corrente o del programma corrente</entry>

            <entry align="center">x</entry>

            <entry align="center">x</entry>
          </row>

          <row>
            <entry><literal>$*</literal></entry>

            <entry>tutti gli argomenti su linea di comando ("$1 $2 ...
              $9")</entry>

            <entry align="center">x</entry>

            <entry align="center">x</entry>
          </row>

          <row>
            <entry><literal>$@</literal></entry>

            <entry>tutti gli argomenti su linea di comando, ciascuno quotato
              separatamente ("$1" "$2" ... "$9")</entry>

            <entry align="center">x</entry>

            <entry align="center"></entry>
          </row>

          <row>
            <entry><literal>$argv[<replaceable>n</replaceable>]</literal></entry>

            <entry>seleziona l'<replaceable>n-esima</replaceable> parola dalla
              lista di input</entry>

            <entry align="center"></entry>

            <entry align="center">x</entry>
          </row>

          <row>
            <entry><literal>${argv[<replaceable>n</replaceable>]}</literal></entry>

            <entry>come sopra</entry>

            <entry align="center"></entry>

            <entry align="center">x</entry>
          </row>

          <row>
            <entry><literal>$#argv</literal></entry>

            <entry>riporta il numero di parole della lista di input</entry>

            <entry align="center"></entry>

            <entry align="center">x</entry>
          </row>
        </tbody>
      </tgroup>
    </table>

    <para>L'uso di queste variabili pu&ograve; essere illustrato con alcuni
      semplici script.  Per la shell Bourne lo script potrebbe essere:</para>

    <programlisting>#!/bin/sh
echo "$#:" $#
echo '$#:' $#
echo '$-:' $-
echo '$?:' $?
echo '$$:' $$
echo '$!:' $!
echo '$3:' $3
echo '$0:' $0
echo '$*:' $*
echo '$@:' $@</programlisting>

    <para>Quando viene eseguito con alcuni argomenti, mostra i valori delle
      variabili di shell, esempio:</para>

    <screen>$ <userinput>./variables.sh one two three four five</userinput>
5: 5
$#: 5
$-:
$?: 0
$$: 12417
$!:
$3: three
$0: ./variables.sh
$*: one two three four five
$@: one two three four five</screen>

    <para>Come si pu&ograve; notare, si ha la necessit&agrave; di usare un
      carattere di quoting singolo per impedire alla shell di assegnare
      significati speciali a $.  Il carattere di quoting doppio, come nella
      prima struttura <command>echo</command>, permette di rimpiazzare il nome
      della variabile con il suo valore.</para>

    <para>Similmente, per le variabili della shell C si possono illustrare le
      sostituzioni di variabili tramite il seguente script:</para>

    <programlisting>#!/bin/csh -f
echo '$$:' $$
echo '$3:' $3
echo '$0:' $0
echo '$*:' $*
echo '$argv[2]:' $argv[2]
echo '${argv[4]}:' ${argv[4]}
echo '$#argv:' $#argv</programlisting>

    <para>che quando eseguito con alcuni argomenti mostra il risultato
      seguente:</para>

    <screen>&prompt.user; <userinput>./variables.csh one two three four five
</userinput>
$$: 12419
$3: three
$0: ./variables.csh
$*: one two three four five
$argv[2]: two
${argv[4]}: four
$#argv: 5</screen>
  </sect1>

  <sect1 id="shell-programming-param-sost">
    <title>Sostituzione di parametri</title>

    <para>Si pu&ograve; riferirsi ai parametri in modo astratto e sostituire i
      loro valori in base a delle condizioni, usando gli operatori definiti qui
      sotto.  Ancora una volta si possono usare le parentesi graffe ({}) per
      isolare la variabile e il suo operatore.</para>

    <informaltable frame="none">
      <tgroup cols="2">
        <colspec colwidth="2in">

        <tbody>
          <row>
            <entry><literal>$<replaceable>parametro</replaceable></literal></entry>

            <entry>sostituisce questa stringa con il valore di
              <replaceable>parametro</replaceable></entry>
          </row>

          <row>
            <entry><literal>${<replaceable>parametro</replaceable>}</literal></entry>

            <entry>come sopra.  Le parentesi sono d'aiuto se non c'&egrave;
              separazione tra questo parametro e una stringa adiacente.</entry>
          </row>

          <row>
            <entry><literal>$<replaceable>parametro</replaceable>=</literal></entry>

            <entry>setta <replaceable>parametro</replaceable> a
              <emphasis>null</emphasis>.</entry>
          </row>

          <row>
            <entry><literal>${<replaceable>parametro</replaceable>-<replaceable>default</replaceable>}</literal></entry>

            <entry>se <replaceable>parametro</replaceable> non &egrave; settato
              allora si usa <replaceable>default</replaceable> come valore.
              <replaceable>parametro</replaceable> non viene resettato.</entry>
          </row>

          <row>
            <entry><literal>${<replaceable>parametro</replaceable>=<replaceable>default</replaceable>}</literal></entry>

            <entry>se <replaceable>parametro</replaceable> non &egrave; settato
              allora lo si setta a <replaceable>default</replaceable> e si usa
              il nuovo valore</entry>
          </row>

          <row>
            <entry><literal>${<replaceable>parametro</replaceable>+<replaceable>nuovo_valore</replaceable>}</literal></entry>

            <entry>se <replaceable>parametro</replaceable> &egrave; settato
              allora si usa <replaceable>nuovo_valore</replaceable> altrimenti
              non si usa nulla.  <replaceable>parametro</replaceable> non viene
              resettato.</entry>
          </row>

          <row>
            <entry><literal>${<replaceable>parametro</replaceable>?<replaceable>messaggio</replaceable>}</literal></entry>

            <entry>se <replaceable>parametro</replaceable> non &egrave; settato
              allora si visualizza il messaggio.  Se
              <replaceable>parametro</replaceable> &egrave; settato allora si
              usa il valore corrente.</entry>
          </row>
        </tbody>
      </tgroup>
    </informaltable>

    <para>Non ci sono spazi nei precedenti operatori.  Se un due punti (:) viene
      inserito prima di  -, =, + o ? allora si effettua prima un test per vedere
      se il parametro ha un settaggio <emphasis>non-nullo</emphasis>.</para>

    <para>La shell C ha alcuni modi aggiuntivi per la sostituzione di
      parametri:</para>

    <informaltable frame="none">
      <tgroup cols="2">
        <colspec colwidth="1.5in">

        <tbody>
          <row>
            <entry><literal>$lista[<replaceable>n</replaceable>]</literal></entry>

            <entry>seleziona l'<replaceable>n-esima</replaceable> parola dalla
              lista</entry>
          </row>

          <row>
            <entry><literal>${lista[<replaceable>n</replaceable>]}</literal></entry>

            <entry>come sopra</entry>
          </row>

          <row>
            <entry><literal>$#lista</literal></entry>

            <entry>riporta il numero di parole in lista</entry>
          </row>

          <row>
            <entry><literal>$?<replaceable>parametro</replaceable></literal></entry>

            <entry>ritorna 1 se il parametro &egrave; settato, 0
              altrimenti</entry>
          </row>

          <row>
            <entry><literal>${?<replaceable>parametro</replaceable>}</literal></entry>

            <entry>come sopra</entry>
          </row>

          <row>
            <entry><literal>$&lt;</literal></entry>

            <entry>legge una linea da &man.stdin.4;</entry>
          </row>
        </tbody>
      </tgroup>
    </informaltable>

    <para>Inoltre la shell C definisce l'array
      <literal>$argv[<replaceable>n</replaceable>]</literal> per
      contenere gli <replaceable>n</replaceable> argomenti della linea di
      comando e <literal>$#argv</literal> per il numero di argomenti, come
      specificato in <link linkend="shell-programming-table-shell-var">Tabella
        9.1</link>.</para>

    <para>Per illustrare alcune di queste caratteristiche si user&agrave; il
      seguente script di prova:</para>

    <programlisting>#!/bin/sh
param0=$0
test -n "$1" && param1=$1
test -n "$2" && param2=$2
test -n "$3" && param3=$3
echo 0: $param0
echo "1: ${param1-1}: \c" ;echo $param1
echo "2: ${param2=2}: \c" ;echo $param2
echo "3: ${param3+3}: \c" ;echo $param3</programlisting>

    <para>Inizialmente nello script si verifica con &man.test.1; se la
      variabile esiste; in tal caso si setta il parametro al suo valore.
      Dopo si riportano i valori, effettuando le sostituzioni.</para>

    <para>Nella prima esecuzione dello script non vengono forniti
      argomenti:</para>

    <screen>$ <userinput>./parameter.sh</userinput>
0: ./parameter.sh       # trova sempre $0
1: 1:                   # sostituisce  1, ma non assegna questo valore
2: 2: 2                 # sostituisce 2 e assegna questo valore
3: :                    # non sostituisce</screen>

    <para>In questa seconda esecuzione dello script si forniscono alcuni
      argomenti:</para>

    <screen>$ <userinput>./parameter one two three</userinput>
0: ./parameter.sh       # trova sempre $0
1: one: one             # non sostituisce, ha gi&agrave; un valore
2: two: two             # non sostituisce, ha gi&agrave; un valore
3: 3: three             # sostituisce 3 ma non assegna questo valore</screen>
  </sect1>

  <sect1 id="shell-programming-here-doc">
    <title>Here document</title>

    <para>Un <emphasis>here document</emphasis> &egrave; una forma di quoting
      che permette alle variabili di shell di essere sostituite.  &Egrave; una
      forma speciale di redirezione che inizia con una linea contenente
      solamente <emphasis>&lt;&lt;<replaceable>PAROLA</replaceable></emphasis>
      e finisce con una linea contenete solamente
      <emphasis><replaceable>PAROLA</replaceable></emphasis>.  Nella shell
      Bourne si pu&ograve; impedire la sostituzione di shell effettuando un
      escape su <emphasis><replaceable>PAROLA</replaceable></emphasis>, mettendo
      un \ davanti a <emphasis><replaceable>PAROLA</replaceable></emphasis>
      sulla linea di redirezione, esempio
      <emphasis>&lt;&lt;\<replaceable>PAROLA</replaceable></emphasis>, ma non
      sulla linea finale.  Per avere lo stesso effetto con la shell C si mette
      il \ davanti a <emphasis><replaceable>PAROLA</replaceable></emphasis> in
      entrambi i posti.</para>

    <para>Gli script che seguono illustrano questo meccanismo:</para>

    <informaltable frame="none">
      <tgroup cols="2">
        <colspec colwidth="3.3in">

        <tbody>
          <row>
            <entry>per la <emphasis>shell Bourne</emphasis>:</entry>

            <entry>e per la <emphasis>shell C:</emphasis></entry>
          </row>
        </tbody>
      </tgroup>
    </informaltable>

    <programlisting>#!/bin/sh                               #!/bin/csh -f
fa=fa                                   set fa = fa
non=""                                  set non = ""
cat &lt;&lt; EOF                              cat &lt;&lt; EOF
Questo here document                    Questo here document
$non $fa                                $non $fa
sostituzione di variabile               sostituzione di variabile
EOF                                     EOF
cat &lt;&lt; \EOF                             cat &lt;&lt; \EOF
Questo here document                    Questo here document
$non $fa                                $non $fa
sostituzione di variabile               sostituzione di variabile
EOF                                     \EOF</programlisting>

    <para>Entrambi gli output producono:</para>

    <screen>Questo here document
fa
sostituzione di variabile
Questo here document
$non $fa
sostituzione di variabile</screen>

    <para>Nella parte superiore dell'esempio le variabili di shell
      <literal>$non</literal> e <literal>$fa</literal> sono sostituite.
      Nella parte inferiore queste variabili vengono trattate come delle
      semplici stringhe di testo senza effettuare la sostituzione.</para>
  </sect1>

  <sect1 id="shell-programming-int-input">
    <title>Input interattivo</title>

    <para>Gli script di shell possono accettare input interattivo per
      inizializzare parametri all'interno dello script stesso.</para>

    <sect2 id="shell-programming-int-input-sh">
      <title>Sh</title>

      <para>&man.sh.1; utilizza il comando built-in <command>read</command> per
        leggere una linea di input, esempio:</para>

      <para><command>read param</command></para>

      <para>Questo pu&ograve; essere illustrato con un semplice script:</para>

      <programlisting>#!/bin/sh
echo "Inserisci una frase \c"   # /bin/echo che richiede "\c" per
                                # impedire un newline
read param
echo param=$param</programlisting>

      <para>Quando questo script viene eseguito, viene richiesto l'input, che
        viene poi mostrato nel risultato:</para>

      <screen>$ <userinput>./read.sh</userinput>
<prompt>Inserisci una frase</prompt> <userinput>hello frank</userinput>  # E' stato digitato hello frank &lt;return&gt;
param=hello frank</screen>
    </sect2>

    <sect2 id="shell-programming-int-input-csh">
      <title>Csh</title>

      <para>&man.csh.1; usa il simbolo <literal>$&lt;</literal> per leggere una
        linea da &man.stdin.4;, esempio:</para>

      <para><command>set param = $<</command></para>

      <para>Gli spazi bianchi intorno al segno di uguale sono importanti.
        Il seguente script illustra come usarlo:</para>

      <programlisting>#!/bin/csh -f
  echo -n "Inserisci una frase"    # Questo echo built-in richiede -n
                                    # per impedire un newline
  set param = $&lt;
  echo param=$param</programlisting>

      <para>Quindi chiede l'input e lo mostra nel risultato:</para>

      <screen>&prompt.user; <userinput>./read.csh</userinput>
<prompt>Inserisci una frase</prompt> <userinput>hello frank</userinput> # E' stato digitato hello frank &lt;return&gt;
param=hello frank</screen>
    </sect2>
  </sect1>

  <sect1 id="shell-programming-functions">
    <title>Funzioni</title>

    <para>La shell Bourne permette di definire funzioni.  Queste sono molto
      simili agli alias della shell C, ma permettono pi&ugrave;
      flessibilit&agrave;.  Una funzione ha la forma:</para>

    <para><command><replaceable>funzione</replaceable> () {
        <replaceable>comando</replaceable>; }</command></para>

    <para>dove lo spazio dopo { e il punto e virgola (;) sono obbligatori;
      il punto e virgola pu&ograve; essere omesso facendo precedere a } un
      newline.  Spazi e newline aggiuntivi sono permessi.
      Alcuni esempi di funzioni possono essere visti nel semplice file
      <filename>.profile</filename> discusso nei primi capitoli, dove si avevano
      delle funzioni per <command>ls</command> e <command>ll</command>:</para>

    <para><command>ls() { /bin/ls -sbF "$@";}</command></para>

    <para><command>ll() { ls -al "$@";}</command></para>

    <para>La prima funzione ridefinisce &man.ls.1; affinch&egrave; le opzioni
      <option>-sbF</option> siano sempre fornite dal comando standard
      <command>/bin/ls</command> e in modo da agire in base all'input fornito,
      <literal>$@</literal>.  La seconda di queste funzioni prende il valore
      corrente di <command>ls</command> (la funzione precedente) e aggiunge le
      opzioni <option>-al</option>.</para>

    <para>Le funzioni sono molto utili negli script di shell.  Il seguente
      script &egrave; una versione semplificata di uno script utilizzato per
      effettuare automaticamente il backup su nastro delle partizioni di
      sistema.</para>

    <programlisting>#!/bin/sh
# Script cron per un completo backup del sistema
HOST=`/bin/uname -n`
admin=frank
Mt=/bin/mt
Dump=/usr/sbin/ufsdump
Mail=/bin/mailx
device=/dev/rmt/0n
Rewind="$Mt -f $device rewind"
Offline="$Mt -f $device rewoffl"
# Failure - exit
failure () {
  $Mail -s "Backup fallito - $HOST" $admin << EOF_failure
  $HOST
  Script cron backup fallito. A quanto pare non c'&egrave; il nastro nel dispositivo.
  EOF_failure
  exit 1
 }
# Dump failure - exit
dumpfail () {
  $Mail -s "Backup fallito - $HOST" $admin << EOF_dumpfail
  $HOST
  Script cron backup fallito. A quanto pare non c'&egrave; il nastro nel dispositivo.
  EOF_dumpfail
  exit 1
 }
# Success
success () {
  $Mail -s "Backup completato con successo - $HOST" $admin << EOF_success
  $HOST
  Script cron backup apparentemente riuscito. Il file /etc/dumpdates &egrave;:
  `/bin/cat /etc/dumpdates`
  EOF_success
  }
# Conferma nastro nel device
$Rewind || failure
$Dump 0uf $device / || dumpfail
$Dump 0uf $device /usr || dumpfail
$Dump 0uf $device /home || dumpfail
$Dump 0uf $device /var || dumpfail
($Dump 0uf $device /var/spool/mail || dumpfail) && success
$Offline</programlisting>

    <para>Questo script illustra alcuni argomenti che sono stati trattati in
      questo documento.  Lo script inizia settando i valori di alcuni parametri.
      <literal>HOST</literal> viene inizializzato dall'output di un comando,
      <literal>admin</literal> &egrave; l'amministratore di sistema,
      <literal>Mt</literal>, <literal>Dump</literal> e <literal>Mail</literal>
      sono nomi di programmi, <literal>device</literal> &egrave; il dispositivo
      speciale usato per accedere al nastro, <literal>Rewind</literal> e
      <literal>Offline</literal> contengono i comandi rispettivamente per
      riavvolgere e scaricare il nastro usando il riferimento
      <literal>Mt</literal> e le necessarie opzioni.  Vengono definite
      tre funzioni: <command>failure</command>, <command>dumpfail</command> e
      <command>success</command>.  Tutte le funzioni in questo script utilizzano
      la forma <emphasis>here document</emphasis> per realizzare il contenuto
      della funzione stessa.  Si introducono ora gli operatori logici
      <emphasis>OR</emphasis> (<emphasis>||</emphasis>) e
      <emphasis>AND</emphasis> (<emphasis>&&</emphasis>); ciascuno &egrave;
      posizionato tra una coppia di comandi.  Per l'operatore
      <emphasis>OR</emphasis>, il secondo comando viene eseguito solamente se
      il primo comando non &egrave; stato completato con successo.  Per
      l'operatore <emphasis>AND</emphasis>, il secondo comando viene
      eseguito solamente se il primo comando &egrave; stato completato con
      successo.</para>

    <para>Lo scopo principale dello script &egrave; realizzare i comandi
      <command>Dump</command>, ad esempio copiando i file system specificati.
      Prima si tenta di eseguire il riavvolgimento del nastro.  Se questo
      fallisce, <literal>|| failure</literal>, si esegue la funzione
      <command>failure</command> e si esce dal programma.  Se invece questo ha
      successo si procede con il backup a turno di ogni partizione, ogni volta
      verificando che questa operazione sia completamente riuscita
      (<literal>|| dumpfail</literal>).  Se questa operazione non viene eseguita
      completamente con successo si esegue la procedura
      <command>dumpfail</command> e si esce.  Se l'ultimo backup ha successo si
      procede con la funzione <command>success</command> (<literal>(...) &&
      success</literal>).  In fine si riavvolge il nastro e lo si manda fuori
      linea affinch&egrave; altri utenti non possano accidentalmente scriverci
      sopra.</para>
  </sect1>

  <sect1 id="shell-programming-control-comm">
    <title>Comandi di controllo</title>

    <sect2 id="shell-programming-control-comm-if">
      <title>Condizionale if</title>

      <para>L'espressione condizionale <command>if</command> &egrave;
        disponibile in entrambe le shell, ma con una diversa sintassi.</para>

      <sect3 id="shell-programming-control-comm-if-sh">
        <title>Sh</title>

        <programlisting><command>if</command> <replaceable>condizione1</replaceable>
<command>then</command>
        lista di comandi se <replaceable>condizione1</replaceable> &egrave; vera (true)
[<command>elif</command> <replaceable>condizione2</replaceable>
        <command>then</command> lista di comandi se <replaceable>condizione2</replaceable> &egrave; vera (true)]
[<command>else</command>
        lista di comandi se <replaceable>condizione1</replaceable> &egrave; falsa (false)]
<command>fi</command></programlisting>

        <para>Le condizioni sono sottoposte usualmente al comando &man.test.1; o
          <command>[]</command> (Vedere la <link
            linkend="shell-programming-control-comm-test">sezione 9.9.6</link>).
          L'<command>if</command> e <command>then</command> devono essere
          separati con un newline o un punto e virgola (;).</para>

        <programlisting>#!/bin/sh
if [ $# -ge 2 ]
then
  echo $2
elif [ $# -eq 1 ]; then
  echo $1
else
  echo Nessun input
fi</programlisting>

        <para>Sono richiesti degli spazi nel formato della condizione di
          &man.test.1;, uno dopo <command>[</command> e uno prima di
          <command>]</command>.  Questo script potrebbe comportarsi in modo
          differente a seconda che ci siano zero, uno o pi&ugrave; argomenti su
          linea di comando.  Iniziando con nessun argomento:</para>

        <screen>$ <userinput>./if.sh</userinput>
Nessun input</screen>

        <para>Ora con un argomento:</para>

        <screen>$ <userinput>./if.sh one</userinput>
one</screen>

        <para>E ora con due argomenti:</para>

        <screen>$ <userinput>./if.sh one two</userinput>
two</screen>
      </sect3>

      <sect3 id="shell-programming-control-comm-if-csh">
        <title>Csh</title>

        <programlisting><command>if</command> (<replaceable>condizione</replaceable>) <command><replaceable>comando</replaceable></command>
   -oppure-
<command>if</command> (<replaceable>condizione1</replaceable>) <command>then</command>
        lista di comandi se <replaceable>condizione1</replaceable> &egrave; vera (true)
[<command>else</command> <command>if</command> (<replaceable>condizione2</replaceable>) <command>then</command>
        lista di comandi se <replaceable>condizione2</replaceable> &egrave; vera (true)]
[<command>else</command>
        lista di comandi se <replaceable>condizione1</replaceable> &egrave; falsa (false)]
<command>endif</command></programlisting>

        <para>L'<command>if</command> e <command>then</command> devono stare
          sulla stessa linea.</para>

        <programlisting>#!/bin/csh -f
if ( $#argv >= 2 ) then
  echo $2
else if ( $#argv == 1 ) then
  echo $1
else
  echo Nessun input
endif</programlisting>

        <para>Di nuovo, questo script potrebbe comportarsi in modo differente a
          seconda che ci siano zero, uno o pi&ugrave; argomenti su linea di
          comando.  Iniziando con nessun argomento:</para>

        <screen>&prompt.user; <userinput>./if.csh</userinput>
Nessun input</screen>

        <para>Ora con un argomento:</para>

        <screen>&prompt.user; <userinput>./if.csh one</userinput>
one</screen>

        <para>E ora con due argomenti:</para>

        <screen>&prompt.user; <userinput>./if.csh one two</userinput>
two</screen>
      </sect3>
    </sect2>

    <sect2 id="shell-programming-control-comm-switch-case">
      <title>Condizionale switch e case</title>

      <para>Per scegliere tra una serie di valori di tipo stringa relativi a un
        parametro si usa <command>case</command> nella shell Bourne e
        <command>switch</command> nella shell C.</para>

      <sect3 id="shell-programming-control-comm-switch-case-sh">
        <title>Sh</title>

        <programlisting><command>case</command> <replaceable>parametro</replaceable> <command>in</command>
        <replaceable>schema1</replaceable>[|<replaceable>schema1a</replaceable>]) <replaceable>lista1 di comandi</replaceable>;;
        <replaceable>schema2</replaceable>) <replaceable>lista2 di comandi</replaceable>
                 <replaceable>lista2a di comandi</replaceable>;;
        <replaceable>schema3</replaceable>) <replaceable>lista3 di comandi</replaceable>;;
        *) ;;
<command>esac</command></programlisting>

        <para>Si possono usare validi nomi di file meta-caratteri all'interno
          dello schema per il confronto.  I ;; concludono ogni scelta e
          possono essere sulla stessa linea della scelta o a seguito di un
          newline, dopo l'ultimo comando per la scelta.  Schemi alternativi
          per la scelta di un particolare caso sono separati da una barra
          verticale |, come nel primo schema dell'esempio precedente.  I simboli
          wild card ,? per indicare un generico carattere e * per far
          corrispondere alcuni caratteri, possono essere usati singolarmente o
          in modo adiacente per completare stringhe.</para>

        <para>Questo semplice esempio illustra come usare l'espressione
          condizionale <command>case</command>.</para>

        <programlisting>#!/bin/sh
case $1 in
        aa|ab) echo A
        ;;
        b?)    echo "B \c"
               echo $1;;
        c*)    echo C;;
        *)     echo D;;
esac</programlisting>

        <para>Quindi quando si esegue lo script con l'argomento posto sulla
          colonna di sinistra, lo script risponde come sulla colonna di
          destra:</para>

        <informaltable frame="none">
          <tgroup cols="2">
            <colspec colwidth="0.5in">

            <tbody>
              <row>
                <entry>aa</entry>

                <entry>A</entry>
              </row>

              <row>
                <entry>ab</entry>

                <entry>A</entry>
              </row>

              <row>
                <entry>ac</entry>

                <entry>D</entry>
              </row>

              <row>
                <entry>bb</entry>

                <entry>B bb</entry>
              </row>

              <row>
                <entry>bbb</entry>

                <entry>D</entry>
              </row>

              <row>
                <entry>c</entry>

                <entry>C</entry>
              </row>

              <row>
                <entry>cc</entry>

                <entry>C</entry>
              </row>

              <row>
                <entry>fff</entry>

                <entry>D</entry>
              </row>
            </tbody>
          </tgroup>
        </informaltable>
      </sect3>

      <sect3 id="shell-programming-control-comm-switch-case-csh">
        <title>Csh</title>

        <programlisting><command>switch</command> (<replaceable>parametro</replaceable>)
<command>case</command> <replaceable>schema1</replaceable>:
        <replaceable>lista1 di comandi</replaceable>
        [<command>breaksw</command>]
<command>case</command> <replaceable>schema2</replaceable>:
        <replaceable>lista2 di comandi</replaceable>
        [<command>breaksw</command>]
<command>default</command>:
        lista di comandi per il comportamento di default
        [<command>breaksw</command>]
<command>endsw</command></programlisting>

        <para><command>breaksw</command> &egrave; opzionale e pu&ograve; essere
          usato per interrompere lo switch dopo che si &egrave; verificata una
          corrispondenza del valore di tipo stringa del parametro confrontato.
          <command>Switch</command> non accetta | nella lista degli schemi, ma
          permette di unire insieme diverse strutture <command>case</command>
          per fornire un simile risultato.  Il seguente script di shell C ha lo
          stesso comportamento dell'esempio precedente, riferito al
          <command>case</command> della shell Bourne.</para>

        <programlisting>#!/bin/csh -f
switch ($1)
        case aa:
        case ab:
                echo A
                breaksw
        case b?:
                echo -n "B "
                echo $1
                breaksw
        case c*:
                echo C
                breaksw
        default:
                echo D
endsw</programlisting>
      </sect3>
    </sect2>

    <sect2 id="shell-programming-control-comm-for-foreach">
      <title>for e foreach</title>

      <para>Per effettuare un ciclo tra una lista di valori di tipo
        stringa si possono usare i comandi <command>for</command> e
        <command>foreach</command>.</para>

      <sect3 id="shell-programming-control-comm-for-foreach-sh">
        <title>Sh</title>

        <programlisting><command>for</command> <replaceable>variabile</replaceable> [<command>in</command> <replaceable>lista_di_valori</replaceable>]
<command>do</command>
        <replaceable>lista di comandi</replaceable>
<command>done</command></programlisting>

        <para>La <replaceable>lista_di_valori</replaceable> &egrave; opzionale,
          presupponendo <literal>$@</literal> se nulla viene specificato.  Ogni
          valore in questa lista viene sostituito sequenzialmente in
          <replaceable>variabile</replaceable> fino a quando la lista risulta
          vuota.  Possono essere usati wild card, che vengono applicati ai
          nomi dei file nella directory corrente.  Di seguito si illustra il
          ciclo <command>for</command> che copia tutti i file che finiscono con
          <filename>.old</filename> negli stessi nomi che finiscono per&ograve;
          con <filename>.new</filename>.  In questi esempi l'utility
          &man.basename.1; estrae la parte base del nome affinch&egrave;
          si possa modificarne l'estensione.</para>

        <programlisting>#!/bin/sh
for file in *.old
do
        newf=`basename $file .old`
        cp $file $newf.new
done</programlisting>
      </sect3>

      <sect3 id="shell-programming-control-comm-for-foreach-csh">
        <title>Csh</title>

        <programlisting><command>foreach</command> <replaceable>variabile</replaceable> (<replaceable>lista_di_valori</replaceable>)
        <replaceable>lista di comandi</replaceable>
<command>end</command></programlisting>

        <para>L'equivalente script in shell C per copiare tutti i file con
          estensione <filename>.old</filename> negli stessi file con estensione
          <filename>.new</filename> &egrave;:</para>

        <programlisting>#!/bin/csh -f
foreach file (*.old)
        set newf = `basename $file .old`
        cp $file $newf.new
end</programlisting>
      </sect3>
    </sect2>

    <sect2 id="shell-programming-control-comm-while">
      <title>while</title>

      <para>Il comando <command>while</command> permette di effettuare il ciclo
        sempre che la condizione sia vera.</para>

      <sect3 id="shell-programming-control-comm-while-sh">
        <title>Sh</title>

        <programlisting><command>while</command> <replaceable>condizione</replaceable>
<command>do</command>
        <replaceable>lista di comandi</replaceable>
        [<command>break</command>]
        [<command>continue</command>]
<command>done</command></programlisting>

        <para>Un semplice script per illustrare il ciclo
          <command>while</command> &egrave;:</para>

        <programlisting>#!/bin/sh
while [ $# -gt 0 ]
do
        echo $1
        shift
done</programlisting>

        <para>Questo script prende la lista degli argomenti, ne visualizza il
          primo, quindi effettua uno shift nella lista verso sinistra, perdendo
          il primo elemento originale.  Il ciclo viene ripetuto fino a quando
          tutti gli argomenti sono stati spostati fuori dalla lista.</para>

        <screen>$ <userinput>./while.sh one two three</userinput>
one
two
three</screen>
      </sect3>

      <sect3 id="shell-programming-control-comm-while-csh">
        <title>Csh</title>

        <programlisting><command>while</command> (<replaceable>condizione</replaceable>)
        <replaceable>lista di comandi</replaceable>
        [<command>break</command>]
        [<command>continue</command>]
<command>end</command></programlisting>

        <para>Se si vuole che la condizione sia sempre vera si specifica 1
          all'interno del test condizionale.</para>

        <para>Lo script di shell C equivalente a quello precedente
          &egrave;:</para>

        <programlisting>#!/bin/csh -f
while ($#argv != 0 )
        echo $argv[1]
        shift
end</programlisting>
      </sect3>
    </sect2>

    <sect2 id="shell-programming-control-comm-until">
      <title>until</title>

      <para>Questo costrutto di ciclo &egrave; solamente disponibile per la
        shell Bourne.</para>

      <programlisting><command>until</command> <replaceable>condizione</replaceable>
<command>do</command>
        lista di comandi se la condizione &egrave; falsa
<command>done</command></programlisting>

      <para>La condizione viene verificata all'inizio di ogni ciclo e il ciclo
        termina quando la condizione &egrave; vera.</para>

      <para>Uno script equivalente all'esempio del <command>while</command>
        precedente &egrave;:</para>

      <programlisting>#!/bin/sh
until [ $# -le 0 ]
do
        echo $1
        shift
done</programlisting>

      <para>Si noti che qui si verifica per <emphasis>minore o
        uguale</emphasis>, piuttosto che per <emphasis>maggiore</emphasis>,
        poich&egrave; il ciclo <command>until</command> viene abilitato da una
        condizione <emphasis>falsa</emphasis>.</para>

      <para>Sia il ciclo <command>until</command> che il
        <command>while</command> sono solamente eseguiti se la condizione
        &egrave; soddisfatta.  La condizione viene valutata prima
        dell'esecuzione dei comandi.</para>
    </sect2>

    <sect2 id="shell-programming-control-comm-test">
      <title>test</title>

      <para>Le espressioni condizionali vengono valutate per valori
        <emphasis>veri</emphasis> o <emphasis>falsi</emphasis>.  Questo, di
        solito, viene realizzato con &man.test.1; o equivalentemente con i suoi
        operatori <command>[]</command>.  Se la condizione viene valutata vera,
        viene settato uno stato di uscita zero (<emphasis>TRUE</emphasis>),
        altrimenti viene settato uno stato di uscita non-zero
        (<emphasis>FALSE</emphasis>).  Se non ci sono argomenti viene settato
        uno stato di uscita non-zero.  Gli operatori utilizzati nelle
        espressioni condizionali della shell Bourne sono mostrati qui
        sotto.</para>

      <para>Per i <emphasis>nomi di file</emphasis> le opzioni per
        &man.test.1; sono date con la sintassi seguente:</para>

      <para><option>-<replaceable>opzione</replaceable></option>
        <replaceable>filename</replaceable></para>

      <para>Le opzioni di &man.test.1; disponibili per i
         <emphasis>file</emphasis> includono:</para>

      <informaltable frame="none">
        <tgroup cols="2">
          <colspec colwidth="1in">

          <tbody>
            <row>
              <entry><option>-r</option></entry>

              <entry>vero se il file esiste ed &egrave; leggibile</entry>
            </row>

            <row>
              <entry><option>-w</option></entry>

              <entry>vero se il file esiste ed &egrave; scrivibile</entry>
            </row>

            <row>
              <entry><option>-x</option></entry>

              <entry>vero se il file esiste ed &egrave; eseguibile</entry>
            </row>

            <row>
              <entry><option>-f</option></entry>

              <entry>vero se il file esiste ed &egrave; un file regolare (o per
                &man.csh.1; esiste e non &egrave; una directory)</entry>
            </row>

            <row>
              <entry><option>-d</option></entry>

              <entry>vero se il file esiste ed &egrave; una directory</entry>
            </row>

            <row>
              <entry><option>-h</option> o <option>-L</option></entry>

              <entry>vero se il file esiste ed &egrave; un link
                simbolico</entry>
            </row>

            <row>
              <entry><option>-c</option></entry>

              <entry>vero se il file esiste ed &egrave; un file speciale a
                caratteri (ad esempio un dispositivo al quale si accede un
                carattere alla volta)</entry>
            </row>

            <row>
              <entry><option>-b</option></entry>

              <entry>vero se il file esiste ed &egrave; un file speciale a
                blocchi (ad esempio un dispositivo al quale si accede in blocchi
                di dati)</entry>
            </row>

            <row>
              <entry><option>-p</option></entry>

              <entry>vero se il file esiste ed &egrave; un file pipe
                (fifo)</entry>
            </row>

            <row>
              <entry><option>-u</option></entry>

              <entry>vero se il file esiste ed &egrave; setuid (ad esempio ha il
                bit set-user-id settato a s o S nel terzo bit)</entry>
            </row>

            <row>
              <entry><option>-g</option></entry>

              <entry>vero se il file esiste ed &egrave; setgid (ad esempio ha il
                bit set-group-id settato a s o S nel sesto bit)</entry>
            </row>

            <row>
              <entry><option>-k</option></entry>

              <entry>vero se il file esiste e ha lo sticky bit settato (una t
                nel nono bit)</entry>
            </row>

            <row>
              <entry><option>-s</option></entry>

              <entry>vero se il file esiste ed ha una dimensione maggiore di
                zero</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>

      <para>C'&egrave; un test per i <emphasis>descrittori di
        file</emphasis>:</para>

      <informaltable frame="none">
        <tgroup cols="2">
          <colspec colwidth="2in">

          <tbody>
            <row>
              <entry><option>-t
                  [<replaceable>descrittore_file</replaceable>]</option></entry>

              <entry>vero se l'aperto descrittore del file specificato (1,
                &man.stdout.4;, di default) &egrave; associato ad un
                terminale</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>

      <para>Ci sono test per le <emphasis>stringhe</emphasis>:</para>

      <informaltable frame="none">
        <tgroup cols="2">
          <colspec colwidth="2in">

          <tbody>
            <row>
              <entry><option>-z
                  <replaceable>stringa</replaceable></option></entry>

              <entry>vero se la lunghezza della stringa &egrave; zero</entry>
            </row>

            <row>
              <entry><option>-n
                  <replaceable>stringa</replaceable></option></entry>

              <entry>vero se la lunghezza della stringa non &egrave;
                zero</entry>
            </row>

            <row>
              <entry><option><replaceable>stringa1</replaceable> =
                  <replaceable>stringa2</replaceable></option></entry>

              <entry>vero se <replaceable>stringa1</replaceable> &egrave;
                identica a <replaceable>stringa2</replaceable></entry>
            </row>

            <row>
              <entry><option><replaceable>stringa1</replaceable> !=
                  <replaceable>stringa2</replaceable></option></entry>

              <entry>vero se <replaceable>stringa1</replaceable> non &egrave;
                identica a <replaceable>stringa2</replaceable></entry>
            </row>

            <row>
              <entry><replaceable>stringa</replaceable></entry>

              <entry>vero se la stringa non &egrave; nulla</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>

      <para>Ci sono dei confronti per gli interi:</para>

      <informaltable frame="none">
        <tgroup cols="2">
          <colspec colwidth="1.5in">

          <tbody>
            <row>
              <entry><option><replaceable>n1</replaceable> -eq
                  <replaceable>n2</replaceable></option></entry>

              <entry>vero se gli interi <replaceable>n1</replaceable> e
                <replaceable>n2</replaceable> sono uguali</entry>
            </row>

            <row>
              <entry><option><replaceable>n1</replaceable> -ne
                  <replaceable>n2</replaceable></option></entry>

              <entry>vero se gli interi <replaceable>n1</replaceable> e
                <replaceable>n2</replaceable> non sono uguali</entry>
            </row>

            <row>
              <entry><option><replaceable>n1</replaceable> -gt
                  <replaceable>n2</replaceable></option></entry>

              <entry>vero se l'intero <replaceable>n1</replaceable> &egrave;
                maggiore dell'intero <replaceable>n2</replaceable></entry>
            </row>

            <row>
              <entry><option><replaceable>n1</replaceable> -ge
                  <replaceable>n2</replaceable></option></entry>

              <entry>vero se l'intero <replaceable>n1</replaceable> &egrave;
                maggiore o uguale dell'intero
                <replaceable>n2</replaceable></entry>
            </row>

            <row>
              <entry><option><replaceable>n1</replaceable> -lt
                  <replaceable>n2</replaceable></option></entry>

              <entry>vero se l'intero <replaceable>n1</replaceable> &egrave;
                minore dell'intero <replaceable>n2</replaceable></entry>
            </row>

            <row>
              <entry><option><replaceable>n1</replaceable> -le
                  <replaceable>n2</replaceable></option></entry>

              <entry>vero se l'intero <replaceable>n1</replaceable> &egrave;
                minore o uguale dell'intero
                <replaceable>n2</replaceable></entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>

      <para>Sono disponibili i seguenti <emphasis>operatori
        logici</emphasis>:</para>

      <informaltable frame="none">
        <tgroup cols="2">
          <colspec colwidth="0.5in">

          <tbody>
            <row>
              <entry><option>!</option></entry>

              <entry>negazione (unaria)</entry>
            </row>

            <row>
              <entry><option>-a</option></entry>

              <entry>and (binario)</entry>
            </row>

            <row>
              <entry><option>-o</option></entry>

              <entry>or (binario)</entry>
            </row>

            <row>
              <entry><option>()</option></entry>

              <entry>le espressioni all'interno di ( ) vengono raggruppate
                insieme. Pu&ograve; essere necessario quotare le parentesi ( )
                per impedire alla shell di interpretarle.</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
    </sect2>

    <sect2 id="shell-programming-control-comm-csh-log-rel-op">
      <title>Operatori relazionali e logici della shell C</title>

      <para>La shell C possiede un suo set di operatori logici e relazionali
        built-in.  In ordine decrescente di priorit&agrave; questi sono:</para>

      <informaltable frame="none">
        <tgroup cols="2">
          <colspec colwidth="1.5in">

          <tbody>
            <row>
              <entry><command>(...)</command></entry>

              <entry>raggruppa espressioni con ( )</entry>
            </row>

            <row>
              <entry><command>~</command></entry>

              <entry>inverso (il suo complemento)</entry>
            </row>

            <row>
              <entry><command>!</command></entry>

              <entry>negazione logica</entry>
            </row>

            <row>
              <entry><command>*, /, %</command></entry>

              <entry>moltiplicazione, divisione, modulo</entry>
            </row>

            <row>
              <entry><command>+, -</command></entry>

              <entry>addizione, sottrazione</entry>
            </row>

            <row>
              <entry><command>&lt;&lt;, &gt;&gt;</command></entry>

              <entry>shift a sinistra di bit, shift a destra di bit</entry>
            </row>

            <row>
              <entry><command>&lt;=</command></entry>

              <entry>minore o uguale</entry>
            </row>

            <row>
              <entry><command>&gt;=</command></entry>

              <entry>maggiore o uguale</entry>
            </row>

            <row>
              <entry><command>&lt;</command></entry>

              <entry>minore</entry>
            </row>

            <row>
              <entry><command>&gt;</command></entry>

              <entry>maggiore</entry>
            </row>

            <row>
              <entry><command>= =</command></entry>

              <entry>uguale</entry>
            </row>

            <row>
              <entry><command>!=</command></entry>

              <entry>non uguale</entry>
            </row>

            <row>
              <entry><command>=~</command></entry>

              <entry>uguale a stringa</entry>
            </row>

            <row>
              <entry><command>!~</command></entry>

              <entry>non uguale a stringa</entry>
            </row>

            <row>
              <entry><command>&amp;</command></entry>

              <entry>AND bit</entry>
            </row>

            <row>
              <entry><command>^</command></entry>

              <entry>XOR bit (or esclusivo)</entry>
            </row>

            <row>
              <entry><command>|</command></entry>

              <entry>OR bit</entry>
            </row>

            <row>
              <entry><command>&amp;&amp;</command></entry>

              <entry>AND logico</entry>
            </row>

            <row>
              <entry><command>||</command></entry>

              <entry>OR logico</entry>
            </row>

            <row>
              <entry><command>{<replaceable>comando</replaceable>}</command></entry>

              <entry>vero (1) se il comando termina con uno stato di uscita 0,
                falso (0) altrimenti.</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>

      <para>Inoltre la shell C permette richieste sul tipo e sui permessi dei
        file con gli operatori seguenti:</para>

      <informaltable frame="none">
        <tgroup cols="2">
          <colspec colwidth="1in">

          <tbody>
            <row>
              <entry><option>-r</option></entry>

              <entry>ritorna vero (1) se il file esiste ed &egrave; leggibile,
                altrimenti ritorna falso (0)</entry>
            </row>

            <row>
              <entry><option>-w</option></entry>

              <entry>vero se il file esiste ed &egrave; scrivibile</entry>
            </row>

            <row>
              <entry><option>-x</option></entry>

              <entry>vero se il file esiste ed &egrave; eseguibile</entry>
            </row>

            <row>
              <entry><option>-f</option></entry>

              <entry>vero se il file esiste e non &egrave; una directory</entry>
            </row>

            <row>
              <entry><option>-d</option></entry>

              <entry>vero se il file esiste ed &egrave; una directory</entry>
            </row>

            <row>
              <entry><option>-e</option></entry>

              <entry>vero se il file esiste</entry>
            </row>

            <row>
              <entry><option>-o</option></entry>

              <entry>vero se l'utente corrente &egrave; il proprietario del
                file</entry>
            </row>

            <row>
              <entry><option>-z</option></entry>

              <entry>vero se il file ha una lunghezza zero (file vuoto)</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
    </sect2>
  </sect1>
</chapter>

<!--
     Local Variables:
     mode: sgml
     sgml-indent-data: t
     sgml-omittag: nil
     sgml-always-quote-attributes: t
     sgml-parent-document: ("../book.sgml" "book" "chapter")
     End:
-->