Shell: Parte 2

Redirezione

I comandi standard:

  • prendono l’input da stdin, standard input; di default stdin e’ l’input utente dato via terminale.
  • scrivono l’output in stdout, standard output; di default stdout e’ il terminale.
  • scrivono eventuali messaggi di errore in stderr, standard error; di default stderr e’ il terminale.

Possiamo modificare questi nomi simbolici usando gli operatori di redirezione:

  • cmd < file costringe cmd ad usare i contenuti di file come stdin.
  • cmd > file costringe cmd a scrivere l’output nel file file. Se file non esiste viene creato, se esiste viene sovrascirtto.
  • cmd >> file costringe cmd a scrivere l’output nel file file. Se file non esiste viene crato, se esiste l’output viene aggiunto alla fine del file.

Avvertimento

Non tutti i comandi permettono di redirigere lo stdin. Tra questi ci sono ls e cat.

Esempio. Lo stdout di ls puo’ comunque essere rediretto verso un file arbitrario:

ls > lista_dei_file.txt

Esempio. Prendiamo il comando echo: di default prende l’input (stdin) dal terminale (qui indicato come “keyboard”) e scrive (stdout) su terminale. Se lanciamo:

echo foo

quello che succede e’ che echo replica (fa l’eco) di tutto quello che scriviamo su terminale e lo stampa sul terminale. In immagini:

Redirezione.

Redirigendo lo stdout di echo a file invece lo costringiamo a redirigere il proprio output nel file:

echo foo > temp.txt

In immagini:

Redirezione.

Esempio. Redirigere l’input di un comando funziona allo stesso modo. Prendiamo il comando wc. Di default prende l’input da schermo:

$ wc -w
foo
bar
baz
Control-d

qui Control-d dice a wc che l’input finisce li’. L’output sara’ 3. Pero’ possiamo costringere wc a leggere l’input da file:

wc -w < temp.txt

In immagini:

Redirezione.

Pipelines

Per eseguire piu’ comandi in sequenza, possiamo usare ;:

cmd1 ; cmd2 ; ... ; cmdN

In questo modo la shell esegue cmd1, poi cmd2, ..., ed infine cmdN.

Si possono combinare piu’ comandi in sequenza con l’operatore di concatetenamento | (pipe). La sintassi e’:

cmd1 | cmd2 | ... | cmdN

L’operatore | collega lo stdout di un comando allo stdin del comando che lo segue.

Una pipeline.

Nota

Il simbolo | rappresenta un tubo!

Esempio. Anticipando un po’ i tempi, se lancio:

ls | tac

ottengo che le righe stampata da ls vengano prese da tac, che le stampa sottosopra.

Esempio. Per stampare su stdout la lista dei file nella mia home con ls e poi contare le righe con wc, scrivo:

ls -l ~ | wc -l

Posso passare argomenti ai vari comandi esattamente come se la pipeline non ci fosse.

Esempio. Per navigare comodamente l’output di una pipeline complessa:

cmd1 | ... | cmdN | less

Il comando less permette di vedere l’output pagina per pagina. Potete spostarvi nell’output come fareste nel manuale: vi spostate con le frecce, potete cercare con /, etc.

Modificare Files

I comandi di base sono:

comando funzione opzioni principali
echo stampa l’eco -n
cat stampa il contenuto di un file -n
tac stampa il contenuto sottosopra  
head stampa l’inzio di un file -n
tail stampa la fine di un file -n

Esempio. Come gia’ visto sopra, il comando echo puo’ essere usato per creare file di testo, ad esempio:

echo 'I am the last line *ever*!' > output.txt
echo 'You are not, you /fool/!' >> output.txt

Qui le virgolette singole ' servono per evitare che la shell reagisca ad eventuali caratteri speciali, nel nostro caso gli asterischi * e gli slash /.

Esercizi

  1. Partendo da ~, controllare il risultato dopo ogni passaggio:
    1. Creare una directory informatica. E’ vuota?
    2. Creare una directory esercizi.
    3. Spostarsi in informatica.
    4. Sempre da dentro informatica, rinominare esercizi in esercizi-shell.
    5. Creare una copia di esercizi-shell in informatica.
    6. Rimuovere la copia originale di esercizi-shell.
    7. Creare in informatica/esercizi-shell un file README, il cui testo deve leggere: “esercitazioni di informatica”.
    8. Aggiungere a README una seconda riga: “Parte 1, introduzione alla shell”.
    9. Tornare alla propria home.
  2. Partendo da ~, controllare il risultato dopo ogni passaggio:
    1. Creare un file di testo a in una nuova directory original. Il file deve contenere la stringa “*”.

    2. Prima di ciascuno dei punti successivi, creare una copia di original chiamata temp.

      1. Creare in temp due copie di a, chiamate b e c.
      2. Che differenza c’e’ tra echo a, ls a e cat a?
      3. Che differenza c’e’ tra mv a b e cp a b; rm a?
      4. Che differenza c’e’ tra cp a b; cp a c e mv a b; mv b c?
      5. Che differenza c’e’ tra mv a z e mkdir z; mv a z?
      6. Che differenza c’e’ tra echo a z e mkdir z; echo a z?
      7. Creare dieci file a1, ..., a10, poi cancellarli con una sola invocazione di rm.
  3. Cosa fa il comando (alcuni dei seguenti comandi sono errati):
    1. ls -e | head -n + 25?
    2. cat | head | tail?
    3. cat .?
    4. echo cat?
    5. cat a > b?
    6. cat << a?
    7. head > a | tail > b?
    8. ls > a; rm < a?
    9. echo KrustyIlKlown > a?
    10. tac < FILE1 | tac > FILE2
  4. Che differenza c’e’ tra (alcuni dei seguenti comandi sono errati):
    1. head < a > b
    2. cat a | head > b
    3. tac a | tac | head > b
    4. tac < a | head | tac > b
  5. Che differenza c’e’ tra:
    1. tac a | head -n 25 > b
    2. cat a | tail -n 25 > b
  6. Che differenza c’e’ tra:
    1. head a | tail
    2. head a > temp; tail a
  7. Che differenza c’e’ tra:
    1. cat file | head
    2. cat | head file
  8. Come faccio a:
    1. stampare l’ennesima riga di un file?
    2. stampare le righe dalla n alla n+m di un file?
  9. Eseguire in ordine:
    1. Creare un file data/b che contenga le stesse righe di data/a, ordinate dalla 26 alla 50, dalla 1 alla 25, e dalla 51 alla 100, in quest’ordine.
    2. Creare un file data/c che contenga le stesse righe di data/a, ordinate dalla 26 alla 50, dalla 25 alla 1, e dalla 51 alla 100, in quest’ordine.