  BASH Programming  - Introduction HOWTO
  di Mike G mikkey@dynamo.com.ar
  Luned 17 Luglio 11:47:00 ART 2000

  Questo articolo si propone di aiutarti ad iniziare a programmare
  script di shell di livello base-intermedio. Non vuole essere un docu
  mento avanzato (vedi il titolo). Io NON sono un esperto o un guru
  della programmazione della shell. Ho deciso di scrivere questo HOWTO
  perch imparer molto e potrebbe essere utile ad altre persone. Qual
  siasi tipo di riscontro sar apprezzato, specialmente se in forma di
  patch :) . Traduzione di William Ghelfi a.k.a. Wiz of Id, Mercoled 19
  Luglio 2000.

  ______________________________________________________________________

  Indice Generale



  1. Introduzione
     1.1 Ottenere l'ultima versione
     1.2 Requisiti
     1.3 Usi di questo documento
     1.4 Traduzioni
     1.5 Note sulla traduzione

  2. Script molto facili
     2.1 Il tradizionale script hello world
     2.2 Uno script di backup molto semplice

  3. Tutto sulla redirezione
     3.1 Teoria e riferimento veloce
     3.2 Esempio: stdout verso file
     3.3 Esempio: stderr verso file
     3.4 Esempio: stdout verso stderr
     3.5 Esempio: stderr verso stdout
     3.6 Esempio: stderr e stdout verso file

  4. Le pipe
     4.1 Che cosa sono e perch vorrai utilizzarle
     4.2 Esempio: semplice pipe con sed
     4.3 Esempio: una alternativa a ls -l *.txt

  5. Variabili
     5.1 Esempio: Hello World! usando le variabili
     5.2 Esempio: Uno script di backup molto semplice (un poco migliore)
     5.3 Variabili locali

  6. Condizionali
     6.1 Pura Teoria
     6.2 Esempio: Esempio basilare di condizionale if .. then
     6.3 Esempio: Esempio basilare di condizionale if .. then ... else
     6.4 Esempio: Condizionali con variabili

  7. Cicli for, while e until
     7.1 Per esempio
     7.2 For simil-C
     7.3 Esempio di while
     7.4 Esempio di until

  8. Funzioni
     8.1 Esempio di funzioni
     8.2 Esempio di funzioni con parametri

  9. Interfacce utente
     9.1 Utilizzo di select per la creazione di semplici men
     9.2 Usare la riga di comando

  10. Varie
     10.1 Leggere l'input dell'utente con read
     10.2 Valutazione aritmetica
     10.3 Trovare bash
     10.4 Prendere il valore di ritorno da un programma
     10.5 Catturare l'output di un programma
     10.6 File a sorgenti multipli

  11. Tavole
     11.1 Operatori di confronto tra stringhe
     11.2 Esempi di confronto tra stringhe
     11.3 Operatori aritmetici
     11.4 Operatori aritmetici relazionali
     11.5 Comandi utili

  12. Altri Script
     12.1 Applicare un comando a tutti i file in una directory.
     12.2 Esempio: Uno script di backup molto semplice (ancora un poco migliore)
     12.3 Rinominatore di file
     12.4 Rinominatore di file (semplice)

  13. Quando qualcosa va male (debugging)
     13.1 Modi di chiamare BASH

  14. Informazioni sul documento
     14.1 (no) warranty
     14.2 Traduzioni
     14.3 Grazie a
     14.4 History
     14.5 Altre risorse


  ______________________________________________________________________

  11..  IInnttrroodduuzziioonnee

  11..11..  OOtttteenneerree ll''uullttiimmaa vveerrssiioonnee

  http://www.linuxdoc.org/HOWTO/Bash-Prog-Intro-HOWTO.html


  IInn iittaalliiaannoo


  http://www.pluto.linux.it/ildp/HOWTO/Bash-Prog-Intro-HOWTO.html

  11..22..  RReeqquuiissiittii

  Familiarit con la riga di comando GNU/Linux e con i concetti di base
  della programmazione, saranno d'aiuto. Nonostante questa non sia una
  introduzione alla programmazione, spiega (o almeno ci prova) molti
  concetti di base.



  11..33..  UUssii ddii qquueessttoo ddooccuummeennttoo

  Questo documento vuol essere utile nei seguenti casi

    Hai un'infarinatura di programmazione e vuoi iniziare a scrivere
     qualche script di shell.

    Hai una vaga idea della programmazione della shell e desideri un
     qualche tipo di riferimento.

    Vuoi vedere qualche script di shell ed alcuni commenti per
     cominciare a scriverne di tuoi.

    Stai passando da DOS/Windows (o l'hai gi fatto) e vuoi preparare
     dei processi "batch".

    Sei un nerd totale ("complete nerd", ndt) e leggi ogni how-to
     disponibile.

  11..44..  TTrraadduuzziioonnii

  Koreano: Chun Hye Jin sconosciuto

  C'erano altre traduzioni, ma non le ho incluse perch non avevo alcun
  URL verso cui puntarle. Se qualcuno di voi ne conoscesse,  pregato di
  inviarmeli via email.


  11..55..  NNoottee ssuullllaa ttrraadduuzziioonnee

  Nel caso vi venisse l'idea (ottima, :-) di inviarmi correzioni in
  formato diff, vi sarei grato se per crearle utilizzaste il comando
  _d_i_f_f _-_u _v_e_c_c_h_i_o_._s_g_m_l _n_u_o_v_o___e___c_o_r_r_e_t_t_o_._s_g_m_l; questo perch la mia
  dabbenaggine mi impedisce di imparare a destreggiarmi con diff che non
  siano stati creati con l'opzione -u.  Grazie e buona lettura!

  22..  SSccrriipptt mmoollttoo ffaacciillii

  Questo HOW-TO tenter di darti alcuni consigli sulla programmazione
  della shell basandosi principalmente su esempi.

  In questa sezione troverai qualche piccolo script che si spera ti sia
  d'aiuto per comprendere alcune tecniche.


  22..11..  IIll ttrraaddiizziioonnaallee ssccrriipptt hheelllloo wwoorrlldd



                 #!/bin/bash
                 echo Hello World



  Questo script ha solamente due righe.  La prima indica al sistema
  quale programma utilizzare per eseguire il file.

  La seconda riga  l'unica azione compiuta dallo script, che stampa
  'Hello World' sul terminale.

  Se ottieni qualcosa come _._/_h_e_l_l_o_._s_h_: _C_o_m_m_a_n_d _n_o_t _f_o_u_n_d_.  Probabilmente
  la prima riga '#!/bin/bash'  errata, controlla dove si trova bash o
  vedi 'trovare bash' per sapere come dovresti modificare tale riga.

  22..22..  UUnnoo ssccrriipptt ddii bbaacckkuupp mmoollttoo sseemmpplliiccee



               #!/bin/bash
               tar -cZf /var/my-backup.tgz /home/me/



  In questo script, invece di stampare un messaggio sul terminale,
  creiamo una tar-ball (archivio tar) della home directory di un utente.
  Questo NON  pensato per essere usato, uno script di backup pi utile
  sar presentato pi avanti in questo documento.

  33..  TTuuttttoo ssuullllaa rreeddiirreezziioonnee

  33..11..  TTeeoorriiaa ee rriiffeerriimmeennttoo vveellooccee

  Esistono 3 descrittori di file: stdin, stdout e stderr (std=standard).


  Basilarmente tu puoi:


  1. redirigere stdout verso un file

  2. redirigere stderr verso un file

  3. redirigere stdout verso stderr

  4. redirigere stderr verso stdout

  5. redirigere stderr e stdout verso un file

  6. redirigere stderr e stdout verso stdout

  7. redirigere stderr e stdout verso stderr

     1 'rappresenta' stdout e 2 stderr.

  Una piccola nota per vedere queste cose: con il comando less puoi
  visualizzare sia stdout (che rester nel buffer) che lo stderr che
  verr stampato sullo schermo, ma eliminato non appena tenterai di
  'sfogliare' il buffer.

  33..22..  EEsseemmppiioo:: ssttddoouutt vveerrssoo ffiillee

  Questo far s che l'output di un programma venga scritto su un file.


               ls -l > ls-l.txt



  Qui, un file chiamato 'ls-l.txt' verr creato e conterr ci che
  vedresti sullo schermo   digitando il comando 'ls -l' ed eseguendolo.

  33..33..  EEsseemmppiioo:: ssttddeerrrr vveerrssoo ffiillee

  Questo far s che l'output di stderr di un programma venga scritto su
  un file.


               grep da * 2> grep-errors.txt



  Qui, un file chiamato 'grep-errors.txt' sar creato e conterr ci che
  vedresti come porzione di stderr dell'output del comando 'grep da *'.

  33..44..  EEsseemmppiioo:: ssttddoouutt vveerrssoo ssttddeerrrr

  Questo far s che l'output di stderr di un programma venga scritto
  sul medesimo filedescriptor di stdout.


               grep da * 1>&2



  Qui, la porzione di stdout del comando  inviata a stderr, puoi
  accorgertene in diversi modi.


  33..55..  EEsseemmppiioo:: ssttddeerrrr vveerrssoo ssttddoouutt

  Questo far s che l'output di stderr di un programma venga scritto
  sul medesimo filedescriptor di stdout.


               grep * 2>&1



  Qui, la porzione di stderr del comando  inviata a stdout, se fai una
  pipe verso less, noterai che righe le quali normalmente 'scomparireb
  bero' (poich sono scritte su stderr) ora vengono tenute (perch si
  trovano su stdout).

  33..66..  EEsseemmppiioo:: ssttddeerrrr ee ssttddoouutt vveerrssoo ffiillee

  Questo porter ogni output di un programma su un file. Pu risultare a
  volte utile per cron, se vuoi che un comando passi in assoluto
  silenzio.


               rm -f $(find / -name core) &> /dev/null



  Questo (pensando a cron) eliminer ogni file chiamato 'core' in qual
  siasi directory. Osserva che dovresti essere piuttosto sicuro di cosa
  sta facendo un comando, prima di eliminarne ogni output.

  44..  LLee ppiippee

  Questa sezione mostra in maniera molto semplice e pratica come usare
  le pipe, e per quale motivo potresti volerlo fare.


  44..11..  CChhee ccoossaa ssoonnoo ee ppeerrcchh vvoorrrraaii uuttiilliizzzzaarrllee

  Le pipe ti permettono di usare (molto semplice, insisto) l'output di
  un programma come input di un altro.

  44..22..  EEsseemmppiioo:: sseemmpplliiccee ppiippee ccoonn sseedd

  Questo  un modo molto semplice di usare le pipe.


               ls -l | sed -e "s/[aeio]/u/g"



  Qui, succede questo: prima  eseguito il comando ls, ed il suo output,
  invece di essere stampato,  inviato (mandato in pipe) al programma
  sed, che a sua volta, stampa quello che ha da stampare.

  44..33..  EEsseemmppiioo:: uunnaa aalltteerrnnaattiivvaa aa llss --ll **..ttxxtt

  Probabilmente, questo  il modo pi difficile per fare ls -l *.txt, ma
   qua per illustrare le pipe, non per risolvere un tale dilemma di
  elencazione.

          ls -l | grep "\.txt$"



  Qui, l'output del programma ls -l  inviato al programma grep, che, a
  sua volta, stamper le righe che corrispondono alla regex "\.txt$".

  55..  VVaarriiaabbiillii

  Puoi usare le variabili come in ogni linguaggio di programmazione.
  Non esistono tipi di dati. Una variabile nella bash pu contenere un
  numero, un carattere, una stringa di caratteri.

  Non hai bisogno di dichiarare una variabile, il solo atto di assegnare
  un valore al suo riferimento far s che venga creata.



  55..11..  EEsseemmppiioo:: HHeelllloo WWoorrlldd!! uussaannddoo llee vvaarriiaabbiillii



                   #!/bin/bash
                   STR="Hello World!"
                   echo $STR



  La riga 2 crea una variabile chiamata STR e le assegna la stringa
  "Hello World!". Poi il VALORE di questa variabile  recuperato
  inserendo il simbolo '$' all'inizio (del riferimento, ndt).  Osserva
  (provaci!)  che se non usi il segno '$', l'output del programma sar
  differente, e probabilmente non quello che avresti voluto fosse.

  55..22..  EEsseemmppiioo:: UUnnoo ssccrriipptt ddii bbaacckkuupp mmoollttoo sseemmpplliiccee ((uunn ppooccoo mmiigglliioorree))



                  #!/bin/bash
                  OF=/var/my-backup-$(date +%Y%m%d).tgz
                  tar -cZf $OF /home/me/



  Questo script introduce un'altra cosa. Prima di tutto, dovresti aver
  dimestichezza con la creazione e l'assegnazione di variabile alla riga
  2.  Osserva l'espressione '$(date +%Y%m%d)'.  Se esegui lo script
  noterai che lancia il comando incluso tra le parentesi, catturando il
  suo output.


  Osserva che in questo script, il nome del file di output sar diverso
  ogni giorno, a causa dell'opzione di formattazione del comando date
  (+%Y%m%d).  Puoi cambiarlo specificando una differente formattazione.


  Altri esempi:

  echo ls

  echo $(ls)

  55..33..  VVaarriiaabbiillii llooccaallii

  Le variabili locali possono essere create utilizzando la keyword
  _l_o_c_a_l.



                       #!/bin/bash
                       HELLO=Hello
                       function hello {
                               local HELLO=World
                               echo $HELLO
                       }
                       echo $HELLO
                       hello
                       echo $HELLO



  Questo esempio dovrebbe essere sufficiente a mostrarti come utilizzare
  una variabile locale.

  66..  CCoonnddiizziioonnaallii

  Le (espressioni, ndt) condizionali ti permettono di decidere se
  compiere o no un'azione. Tale decisione  presa valutando
  un'espressione.


  66..11..  PPuurraa TTeeoorriiaa

  Le (espressioni, ndt) condizionali hanno varie forme. La forma pi
  basilare : iiff _e_s_p_r_e_s_s_i_o_n_e tthheenn _i_s_t_r_u_z_i_o_n_e dove 'istruzione' viene
  eseguita solamente se 'espressione' ha valore "vero". '2<1'  una
  espressione che ha valore "falso", mentre '2>1' ha valore "vero".

  Le condizionali hanno altre forme come: iiff _e_s_p_r_e_s_s_i_o_n_e tthheenn
  _i_s_t_r_u_z_i_o_n_e_1 eellssee _i_s_t_r_u_z_i_o_n_e_2.  Qui 'istruzione'  eseguita se
  'espressione'  vera, altrimenti viene eseguita        'istruzione2'.

  Ancora un'altra forma di (espressione, ndt) condizionale : iiff
  _e_s_p_r_e_s_s_i_o_n_e_1 tthheenn _i_s_t_r_u_z_i_o_n_e_1 eellssee iiff _e_s_p_r_e_s_s_i_o_n_e_2 tthheenn _i_s_t_r_u_z_i_o_n_e_2
  eellssee _i_s_t_r_u_z_i_o_n_e_3.  In questa forma  stato aggiunto solamente "ELSE IF
  'espressioen2' THEN 'istruzione2'" che fa eseguire istruzione2 se
  espressione2 vale "vero".  Il resto  come ti puoi immaginare (vedi le
  forme precedenti).

  Una parola sulla sintassi:

  La base per i costrutti 'if' nella bash  questa:

  if [espressione];

  then

  codice eseguito se 'espressione'  vera.


  fi

  66..22..  EEsseemmppiioo:: EEsseemmppiioo bbaassiillaarree ddii ccoonnddiizziioonnaallee iiff .... tthheenn



                   #!/bin/bash
                   if [ "foo" = "foo" ]; then
                      echo expression evaluated as true
                   fi



  Il codice da eseguire se l'espressione tra parentesi quadre  vera pu
  trovarsi solamente dopo la parola 'then' e prima del 'fi' che indica
  la fine del codice eseguito sotto condizione.

  66..33..  EEsseemmppiioo:: EEsseemmppiioo bbaassiillaarree ddii ccoonnddiizziioonnaallee iiff .... tthheenn ...... eellssee



                   #!/bin/bash
                   if [ "foo" = "foo" ]; then
                      echo expression evaluated as true
                   else
                      echo expression evaluated as false
                   fi



  66..44..  EEsseemmppiioo:: CCoonnddiizziioonnaallii ccoonn vvaarriiaabbiillii



                   #!/bin/bash
                   T1="foo"
                   T2="bar"
                   if [ "$T1" = "$T2" ]; then
                       echo expression evaluated as true
                   else
                       echo expression evaluated as false
                   fi



  77..  CCiiccllii ffoorr,, wwhhiillee ee uunnttiill

  In questa sezione troverai cicli for, while e until.

  Il ciclo ffoorr  leggermente diverso da quello degli altri linguaggi di
  programmazione. Basilarmente, ti permette un'iterazione su una serie
  di 'parole' in una stringa.

  Il wwhhiillee esegue una porzione di codice se l'espressione di controllo 
  vera, e si ferma esclusivamente quando  falsa (o viene raggiunta
  un'interruzione esplicita all'interno del codice eseguito).


  Il ciclo uunnttiill  all'incirca uguale al ciclo while, solo che il codice
   eseguito finch l'espressione di controllo ha valore "falso".

  Se hai il sospetto che while e until siano molto simili hai ragione.


  77..11..  PPeerr eesseemmppiioo



               #!/bin/bash
               for i in $( ls ); do
                   echo item: $i
               done



  Sulla seconda riga, dichiariamo i come la variabile che prender i
  differenti valori contenuti in $( ls ).

  La terza riga potrebbe essere pi lunga se necessario, o ci potrebbero
  essere pi righe prima del done (4).

  `done' (4) indica che il codice che ha utilizzato il valore di $i 
  terminato e $i pu ricevere un nuovo valore.

  Questo script ha veramente poco senso, ma un modo pi utile per
  utilizzare il ciclo for sarebbe di usarlo per isolare ("to match",
  ndt) solo certi file nell'esempio precedente.


  77..22..  FFoorr ssiimmiill--CC

  fiesh ha suggerito di aggiungere questo modo di eseguire un ciclo. Si
  tratta di un ciclo for pi simile al for dei linguaggi C/perl...


               #!/bin/bash
               for i in `seq 1 10`;
               do
                       echo $i
               done



  77..33..  EEsseemmppiioo ddii wwhhiillee



                #!/bin/bash
                COUNTER=0
                while [  $COUNTER -lt 10 ]; do
                    echo The counter is $COUNTER
                    let COUNTER=COUNTER+1
                done



  Questo script 'emula' la ben conosciuta struttura 'for' dei linguaggi
  C, Pascal, perl, etc.

  77..44..  EEsseemmppiioo ddii uunnttiill



                #!/bin/bash
                COUNTER=20
                until [  $COUNTER -lt 10 ]; do
                    echo COUNTER $COUNTER
                    let COUNTER-=1
                done



  88..  FFuunnzziioonnii

  Come in quasi ogni linguaggio di programmazione, puoi utilizzare le
  funzioni per raggruppare porzioni di codice in modo pi logico oppure
  praticare la divina arte della ricorsione (ricorsivit, ndt).

  Dichiarare una funzione  giusto questione di scrivere function
  mia_funzione { mio_codice }.

  Chiamare una funzione  proprio come chiamare un altro programma,
  semplicemente scrivi il suo nome.


  88..11..  EEsseemmppiioo ddii ffuunnzziioonnii



                  #!/bin/bash
                  function quit {
                      exit
                  }
                  function hello {
                      echo Hello!
                  }
                  hello
                  quit
                  echo foo



  Le righe 2-4 contengono la funzione 'quit'. Le righe 5-7 contengono la
  funzione 'hello'.  Se non sei assolutamente sicuro di cosa faccia
  questo script, sei pregato di provarlo!.

  Osserva che le funzioni non hanno bisogno di essere dichiarate in
  alcun ordine particolare.

  Lanciando questo script lo noterai per la prima volta: la funzione
  'hello'  chiamata, per seconda la funzione 'quit', e il programma non
  raggiunge mai la riga 10.



  88..22..  EEsseemmppiioo ddii ffuunnzziioonnii ccoonn ppaarraammeettrrii



                       #!/bin/bash
                       function quit {
                          exit
                       }
                       function e {
                           echo $1
                       }
                       e Hello
                       e World
                       quit
                       echo foo



  Questo script  praticamente identico al precedente. La differenza
  principale  la funzione 'e'. Tale funzione, stampa il primo argomento
  che riceve.  Gli argomenti, nell'ambito delle funzioni, vengono
  trattati nella stessa maniera degli argomenti passati allo script.

  99..  IInntteerrffaaccccee uutteennttee

  99..11..  UUttiilliizzzzoo ddii sseelleecctt ppeerr llaa ccrreeaazziioonnee ddii sseemmpplliiccii mmeenn



                  #!/bin/bash
                  OPTIONS="Hello Quit"
                  select opt in $OPTIONS; do
                      if [ "$opt" = "Quit" ]; then
                       echo done
                       exit
                      elif [ "$opt" = "Hello" ]; then
                       echo Hello World
                      else
                       clear
                       echo bad option
                      fi
                  done



  Se lanci questo script vedrai che si tratta di quel che i
  programmatori sognano per i men testuali. Probabilmente noterai che 
  molto simile al costrutto 'for', solo che invece di eseguire il ciclo
  per ogni 'parola' in $OPTIONS, richiede input all'utente.


  99..22..  UUssaarree llaa rriiggaa ddii ccoommaannddoo



            #!/bin/bash
            if [ -z "$1" ]; then
                echo usage: $0 directory
                exit
            fi
            SRCD=$1
            TGTD="/var/backups/"
            OF=home-$(date +%Y%m%d).tgz
            tar -cZf $TGTD$OF $SRCD



  Ci che fa questo script ti dovrebbe essere chiaro. L'espressione
  nella prima condizionale controlla se il programma ha ricevuto un
  argomento ($1) e ed esce in caso negativo, mostrando all'utente un
  breve messaggio di utilizzo.  A questo punto il resto dello script
  dovrebbe esserti chiaro.

  1100..  VVaarriiee

  1100..11..  LLeeggggeerree ll''iinnppuutt ddeellll''uutteennttee ccoonn rreeaadd

  In molte occasioni potresti voler richiedere l'utente un certo input,
  Ci sono diversi modi per raggiungere tale scopo. Eccone uno:


                       #!/bin/bash
                       echo Please, enter your name
                       read NAME
                       echo "Hi $NAME!"



  Come variante, puoi ottenere valori multipli con read, questo esempio
  dovrebbe chiarire il concetto.


                       #!/bin/bash
                       echo Please, enter your firstname and lastname
                       read FN LN
                       echo "Hi! $LN, $FN !"



  1100..22..  VVaalluuttaazziioonnee aarriittmmeettiiccaa

  Dalla riga di comando (o da una shell) prova questo:

  echo 1 + 1

  Se ti aspettavi di vedere '2' sarai dispiaciuto. Che fare se vuoi che
  BASH processi dei numeri che hai? Ecco la soluzione:

  echo $((1+1))

  Questo produrr un output pi 'logico'. Questo per valutare
  espressione aritmetica. Puoi ottenere lo stesso risultato con qualcosa
  come:
  echo $[1+1]


  Se hai bisogno di usare le frazioni, o operazioni pi complesse ("more
  math", ndt), o semplicemente perch ne hai voglia, puoi utilizzare bc
  per processare le espressioni aritmetiche.

  Se eseguissi "echo $[3/4]" al prompt dei comandi, mi restituirebbe 0
  poich bash usa solamente interi in fase di risposta. Eseguendo "echo
  3/4|bc -l", ti restituirebbe un pi adeguato 0.75.

  1100..33..  TTrroovvaarree bbaasshh

  Da un messaggio di mike (vedi Grazie a)

  tu usi sempre #!/bin/bash .. potresti fornire un esempio di come

  scoprire dove si trovi bash.

  `locate bash'  preferibile, ma non tutte le macchine hanno locate.

  `find ./ -name bash' dalla root directory (quella indicata con /,

  ndt) funziona, in genere.

  Suggerimenti su dove cercare:

  ls -l /bin/bash

  ls -l /sbin/bash

  ls -l /usr/local/bin/bash

  ls -l /usr/bin/bash

  ls -l /usr/sbin/bash

  ls -l /usr/local/sbin/bash

  (non me vengono in mente altri al momento. (l'ho trovata nella

  maggior parte di questi posti in sistemi diversi).

  Puoi provare anche 'which bash'.

  1100..44..  PPrreennddeerree iill vvaalloorree ddii rriittoorrnnoo ddaa uunn pprrooggrraammmmaa

  Nella bash, il valore di ritorno di un programma  memorizzato in
  variabile speciale chiamata $?.

  Questo mostra come catturare il valore restituito da un programma;
  faccio conto che la directory _d_a_d_a non esista. (Anche questo  stato
  suggerito da mike)


               #!/bin/bash
               cd /dada &> /dev/null
               echo rv: $?
               cd $(pwd) &> /dev/null
               echo rv: $?



  1100..55..  CCaattttuurraarree ll''oouuttppuutt ddii uunn pprrooggrraammmmaa

  Questo piccolo script mostra tutte le tabelle da tutti i database
  (assumendo che tu abbia MySQL installato).  Inoltre, considera la
  possibilit di modificare il comando 'mysql' per aggiungere uno
  username ed una password validi.


               #!/bin/bash
               DBS=`mysql -uroot  -e"show databases"`
               for b in $DBS ;
               do
                       mysql -uroot -e"show tables from $b"
               done



  1100..66..  FFiillee aa ssoorrggeennttii mmuullttiippllii

  Puoi usare pi di un file per volte tramite il comando source.

  __TO-DO__

  1111..  TTaavvoollee

  1111..11..  OOppeerraattoorrii ddii ccoonnffrroonnttoo ttrraa ssttrriinngghhee

  (1) s1 = s2

  (2) s1 != s2

  (3) s1 < s2

  (4) s1 > s2

  (5) -n s1

  (6) -z s1



  (1) s1 corrisponde a s2

  (2) s1 non corrisponde a s2

  (3) __TO-DO__

  (4) __TO-DO__

  (5) s1 non  vuota (contiene uno o pi caratteri)

  (6) s1  vuota

  1111..22..  EEsseemmppii ddii ccoonnffrroonnttoo ttrraa ssttrriinngghhee

  Confrontare due stringhe.



          #!/bin/bash
          S1='string'
          S2='String'
          if [ $S1=$S2 ];
          then
                  echo "S1('$S1') is not equal to S2('$S2')"
          fi
          if [ $S1=$S1 ];
          then
                  echo "S1('$S1') is equal to S1('$S1')"
          fi



  Riporto qui una nota da una mail, inviata da Andreas Beck, in
  riferimento all'uso di _i_f _[ _$_1 _= _$_2 _].

  Non  proprio una buona idea, dato che se una tra $S1 ed $S2  vuota,
  riceverai un errore di sintassi. x$1=x$2 oppure "$1"="$2" vanno
  meglio.


  1111..33..  OOppeerraattoorrii aarriittmmeettiiccii

  +

  -

  *

  /

  % (resto della divisione)

  1111..44..  OOppeerraattoorrii aarriittmmeettiiccii rreellaazziioonnaallii

  -lt (<)

  -gt (>)

  -le (<=)

  -ge (>=)

  -eq (==)

  -ne (!=)

  I programmatori in C dovrebbero limitarsi a mappare l'operatore alla
  parentesi corrispondente.

  1111..55..  CCoommaannddii uuttiillii

  Questa sezione  stata riscritta da Kees (vedi Grazie a...)

  Alcuni di questi comandi quasi prevedono completi linguaggi di
  programmazione.  Per tali comandi saranno spiegate soltanto le basi.
  Per una descrizione pi dettagliata, ti consiglio una lettura pi
  approfondita alle pagine man di ciascun comando.

  sseedd (stream editor)



  Sed  un editor non interattivo. Invece di alterare un file muovendo
  il cursore sullo schermo, usi uno script di istruzioni di editing per
  sed, pi il nome del file da editare. Puoi considerare sed anche come
  un filtro.  Diamo un'occhiata ad alcuni esempi:



               $sed 's/vecchio_testo/testo_che_lo_sostituisce/g' /tmp/dummy



  Sed rimpiazza la stringa 'vecchio_testo' con la stringa
  'testo_che_lo_sostituisce' e legge dal file /tmp/dummy. Il risultato
  sar inviato a stdout (normalmente la consolle) ma puoi anche
  aggiungere '> cattura' alla fine della riga qua sopra cos che sed
  invii l'output al file 'cattura'.



               $sed 12, 18d /tmp/dummy



  Sed mostra tutte le righe tranne quelle da 12 a 18. Il file originale
  non  alterato da questo comando.

  aawwkk (manipolazione di datafile, recuperare testo e processarlo)


  Esistono molte implementazioni del linguaggio di programmazione AWK
  (gli interpreti pi conosciuti sono gawk della GNU e 'new awk' mawk.)
  Il principio  semplice: AWK ricerca un modello, e per ogni
  corrispondenza verr compiuta una azione.

  Di nuovo, ho creato un file dummy contente le seguenti righe:

  _"_t_e_s_t_1_2_3

  _t_e_s_t

  _t_t_e_e_s_s_t_t_"



               $awk '/test/ {print}' /tmp/dummy



  test123


  test


  Il modello cercato da AWK  'test' e l'azione che compie quando trova
  una riga nel file /tmp/dummy con la stringa 'test'  'print' (stampa,
  ndt).
               $awk '/test/ {i=i+1} END {print i}' /tmp/dummy



  3


  Quando stai cercando pi di un modello, sarebbe meglio se sostituissi
  il testo tra apici con '-f file.awk' cos da poter inserire tutti i
  modelli e le azioni nel file 'file.awk'.

  ggrreepp (stampa righe che corrispondono ad un modello di ricerca)


  Abbiamo gi incontrato un paio di comandi grep nei capitoli
  precedenti, che mostrano le righe corrispondenti ad un modello. Ma
  grep sa fare di pi.


               $grep "la sto cercando" /var/log/messages -c



  12

  La stringa "la sto cercando"  stata trovata 12 volte nel file
  /var/log/messages.

  [ok, questo esempio era uno scherzo, il file /var/log/messages era
  preparato :-)]

  wwcc (conta righe, parole e byte)


  Nell'esempio seguente, notiamo che l'output non  quello che ci
  aspettavamo. Il file dummy, cos come  usato in questo esempio,
  contiene il seguente testo: _"_b_a_s_h _i_n_t_r_o_d_u_c_t_i_o_n
   _h_o_w_t_o _t_e_s_t _f_i_l_e_"



               $wc --words --lines --bytes /tmp/dummy



  2 5 34 /tmp/dummy


  Wc non si cura dell'ordine dei parametri. Wc li stampa sempre
  nell'ordine standard, cio, come puoi vedere:
  <righe><parole><byte><nomefile>.

  ssoorrtt (ordina le righe dei file di testo)


  Questa volta il file dummy contiene il seguente testo:


  _"_b

  _c

  _a_"


               $sort /tmp/dummy



  Ecco come dovrebbe apparire l'output:


  _a

  _b

  _c


  I comandi non dovrebbero essere cos semplici :-)

  bbcc (un linguaggio di programmazione che fa da calcolatrice)


  Bc accetta calcoli dalla riga di comando (input da un file. Non da un
  operatore di redirezione e da una pipe), ma anche da una interfaccia
  utente.  La seguente dimostrazione presenta alcuni dei comandi.
  Osserva che io lancio

  bc usando il parametro -q per evitare un messaggio di benvenuto.



          $bc -q



  _1 _=_= _5

  _0

  _0_._0_5 _=_= _0_._0_5

  _1

  _5 _!_= _5

  _0

  _2 _^ _8

  _2_5_6

  _s_q_r_t_(_9_)

  _3


  _w_h_i_l_e _(_i _!_= _9_) _{

  _i _= _i _+ _1_;

  _p_r_i_n_t _i

  _}

  _1_2_3_4_5_6_7_8_9

  _q_u_i_t

  ttppuutt (inizializza un terminale o interroga il database di terminfo)


  Una piccola dimostrazione delle capacit di tput:


               $tput cup 10 4



  Il prompt appare a (y10,x4).


               $tput reset



  Pulisce lo schermo e il prompt appare a (y1,x1). Nota che (y0,x0) 
  l'angolo in alto a sinistra.


               $tput cols



  _8_0

  Mostra il numero di caratteri possibili in direzione x.

   vivamente raccomandato di familiarizzare con questi programmi (al
  meno ). Ci sono tonnellate di piccoli programmi che ti permetteranno
  di fare delle vere magie dalla riga di comando.

  [alcuni esempi sono tratti da pagine man o FAQ]

  1122..  AAllttrrii SSccrriipptt

  1122..11..  AApppplliiccaarree uunn ccoommaannddoo aa ttuuttttii ii ffiillee iinn uunnaa ddiirreeccttoorryy..



  1122..22..  EEsseemmppiioo:: UUnnoo ssccrriipptt ddii bbaacckkuupp mmoollttoo sseemmpplliiccee ((aannccoorraa uunn ppooccoo
  mmiigglliioorree))



              #!/bin/bash
              SRCD="/home/"
              TGTD="/var/backups/"
              OF=home-$(date +%Y%m%d).tgz
              tar -cZf $TGTD$OF $SRCD



  1122..33..  RRiinnoommiinnaattoorree ddii ffiillee



               #!/bin/sh
               # renna: rename multiple files according to several rules
               # written by felix hudson Jan - 2000

               #first check for the various 'modes' that this program has
               #if the first ($1) condition matches then we execute that portion of the
               #program and then exit

               # check for the prefix condition
               if [ $1 = p ]; then

               #we now get rid of the mode ($1) variable and prefix ($2)
                 prefix=$2 ; shift ; shift

               # a quick check to see if any files were given
               # if none then its better not to do anything than rename some non-existent
               # files!!

                 if [$1 = ]; then
                    echo "no files given"
                    exit 0
                 fi

               # this for loop iterates through all of the files that we gave the program
               # it does one rename per file given
                 for file in $*
                   do
                   mv ${file} $prefix$file
                 done

               #we now exit the program
                 exit 0
               fi

               # check for a suffix rename
               # the rest of this part is virtually identical to the previous section
               # please see those notes
               if [ $1 = s ]; then
                 suffix=$2 ; shift ; shift

                  if [$1 = ]; then
                   echo "no files given"
                  exit 0
                  fi

                for file in $*
                 do
                  mv ${file} $file$suffix
                done

                exit 0
               fi

               # check for the replacement rename
               if [ $1 = r ]; then

                 shift

               # i included this bit as to not damage any files if the user does not specify
               # anything to be done
               # just a safety measure

                 if [ $# -lt 3 ] ; then
                   echo "usage: renna r [expression] [replacement] files... "
                   exit 0
                 fi
               # remove other information
                 OLD=$1 ; NEW=$2 ; shift ; shift

               # this for loop iterates through all of the files that we give the program
               # it does one rename per file given using the program 'sed'
               # this is a sinple command line program that parses standard input and
               # replaces a set expression with a give string
               # here we pass it the file name ( as standard input) and replace the nessesary
               # text

                 for file in $*
                 do
                   new=`echo ${file} | sed s/${OLD}/${NEW}/g`
                   mv ${file} $new
                 done
               exit 0
               fi

               # if we have reached here then nothing proper was passed to the program
               # so we tell the user how to use it
               echo "usage;"
               echo " renna p [prefix] files.."
               echo " renna s [suffix] files.."
               echo " renna r [expression] [replacement] files.."
               exit 0

               # done!



  1122..44..  RRiinnoommiinnaattoorree ddii ffiillee ((sseemmpplliiccee))



            #!/bin/bash
            # renames.sh
            # basic file renamer

            criteria=$1
            re_match=$2
            replace=$3

            for i in $( ls *$criteria* );
            do
                src=$i
                tgt=$(echo $i | sed -e "s/$re_match/$replace/")
                mv $src $tgt
            done



  1133..  QQuuaannddoo qquuaallccoossaa vvaa mmaallee ((ddeebbuuggggiinngg))

  1133..11..  MMooddii ddii cchhiiaammaarree BBAASSHH

  Una cosa carina da fare  di aggiungere alla prima riga


                 #!/bin/bash -x


  Ci produrr un po' di interessanti informazioni di output

  1144..  IInnffoorrmmaazziioonnii ssuull ddooccuummeennttoo

  Sentiti libero di proporre suggerimenti/correzioni, o qualunque cosa
  tu pensi che potrebbe essere interessante vedere in questo documento.
  Io cercher di aggiornarlo al pi presto possibile.

  1144..11..  ((nnoo)) wwaarrrraannttyy

  This documents comes with no warranty of any kind.  and all that

  1144..22..  TTrraadduuzziioonnii

  Italiano: a cura di Willy is here

  Francese: a cura di Laurent Martelli is missed

  Sono convinto che esistano altre traduzioni, ma non ne ho alcuna
  notizia; se voi le avete, per piacere, mandatemele via email cosi
  potr aggiornare questa sezione.

  1144..33..  GGrraazziiee aa


    Le persone che hanno tradotto questo documento in altre lingue
     (sezione precedente).

    Nathan Hurst per avermi mandato un sacco di correzioni.

    Jon Abbott per aver inviato commenti sulla valutazione delle
     espressioni aritmetiche.

    Felix Hudson per aver scritto lo script _r_e_n_n_a.

    Kees van den Broek (per aver inviato molte correzioni, riscritto la
     sezione dei comandi utili).

    Mike (pink) ha avanzato qualche suggerimento su come trovare bash e
     testare i file.

    Fiesh ha avanzato un buon suggerimento per la sezione dei cicli.

    Lion ha suggerito di menzionare un errore comune (./hello.sh:
     Command not found.).

    Andreas Beck ha fatto diverse correzioni e commenti.

  1144..44..  HHiissttoorryy

  Aggiunta la sezione comandi utili riscritta da Kess.

  Inclusi molti suggerimenti e correzioni.

  Aggiunti esempi sul confronto tra stringhe.

  v0.8 abbandonata la numerazione delle versioni, credo che la data sia
  abbastanza.

  v0.7 Altre correzioni e alcune vecchie sezioni TO-DO riscritte.

  v0.6 Correzioni minori.

  v0.5 Aggiunta la sezione sulla redirezione.


  v0.4 Scomparsa dalla sua locazione a causa del mio ex-capo e questo
  documento ha trovato il suo nuovo posto all'opportuno url:
  www.linuxdoc.org.

  precedenti: non mi ricordo e non usavo rcs o cvs :(

  1144..55..  AAllttrree rriissoorrssee


  Introduction to bash (under BE)
  http://org.laol.net/lamug/beforever/bashtut.htm

  Bourne Shell Programming http://207.213.123.70/book/



