[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [volume] [parte]


Capitolo 141.   Shell POSIX: accesso ai file

La shell POSIX ha una capacità limitata ad accedere ai file in modo sequenziale. Ciò consente di fare qualcosa di interessante negli script.

141.1   Utilizzo dei descrittori

Generalmente, si utilizzano i tre flussi standard in modo intuitivo, senza la necessità di aprirli o di chiuderli. Quando si vogliono gestire più flussi di dati simultaneamente, occorre attivare altri descrittori.

Tabella 141.1. Descrittori standard.

Descrittore Apertura Standard
0 lettura standard input
1 scrittura standard output
2 scrittura standard error

I descrittori dei flussi standard risultano aperti senza bisogno di una richiesta esplicita; per aprire dei descrittori ulteriori, occorre dare delle istruzioni appropriate nella riga di comando:

Comando Descrizione
comando ... n< file
Apre il file in lettura e ne consente l'accesso al comando attraverso il descrittore numero n.
comando ... n> file
Apre il file in scrittura, azzerandolo inizialmente, concedendone l'accesso al comando attraverso il descrittore numero n.
comando ... n>> file
Apre il file in scrittura, per l'aggiunta di dati in coda, concedendone l'accesso al comando attraverso il descrittore numero n.

Generalmente, i descrittori aperti durante l'esecuzione di uno script, vengono chiusi automaticamente al termine del funzionamento dello stesso; in alternativa possono essere chiusi esplicitamente con la sintassi seguente:

n<&-

È da osservare che in questo modo si chiude il descrittore n, indipendentemente dal fatto che rappresentasse un flusso in ingresso (lettura), o in uscita (scrittura).

All'interno di uno script è possibile aprire dei descrittori alla chiamata di una funzione, come nell'esempio seguente:

#!/bin/sh
...
function fa_qualcosa () {
    ...
}
...
fa_qualcosa 3< mio_file
...

Teoricamente, è possibile aprire un descrittore in lettura in modo più semplice, senza che ciò debba avvenire necessariamente alla chiamata di un comando, ma l'uso di una shell poco amichevole, sotto questo punto di vista, potrebbe rendere la cosa del tutto inutile. Pertanto, pur essendo un procedimento sconsigliabile, ecco come si potrebbe procedere:

#!/bin/sh
...
3< mio_file    # apre il file nel descrittore n. 3
...
# qui si fa qualcosa con il descrittore n. 3
...
3<&-    # chiude il file associato al descrittore n. 3
...

141.2   Lettura e scrittura

La lettura da un descrittore si ottiene con il comando read:

read [-p prompt] variabile...

Il comando read legge dallo standard input, pertanto, per leggere un flusso di dati proveniente attraverso un altro descrittore, occorre inserirlo nello standard input:

read [-p prompt] variabile... <&n

Per leggere i dati provenienti da un file, aperto attraverso il descrittore n, si può usare un ciclo simile a quello seguente, dove si deve elaborare una riga alla volta del file originale:

while read RIGA_DEL_FILE <&n
do
    #
    # Fa qualcosa con il contenuto della variabile di ambiente
    # RIGA_DEL_FILE.
    #
    ...
done

Per scrivere qualcosa all'interno di un descrittore, si usano normalmente i comandi echo o printf. Entrambi questi comandi scrivono attraverso lo standard output, pertanto, anche in questo caso, occorre ridirigere il flusso verso il descrittore desiderato, se necessario. L'esempio seguente legge un file attraverso il descrittore n e lo emette, tale e quale, attraverso il descrittore m, elaborando i dati riga per riga:

while read RIGA_DEL_FILE <&n
do
    echo "$RIGA_DEL_FILE" >&m
done

L'esempio successivo legge dallo standard input e scrive attraverso lo standard output, dopo aver trasformato il testo in maiuscolo (considerando soltanto l'alfabeto latino senza lettere accentate):

#!/bin/sh
while read RIGA
do
    echo $RIGA | tr a-z A-Z
done

L'esempio seguente fa la stessa cosa utilizzando il descrittore numero 3 per la lettura del file e il descrittore numero 4 per la scrittura:

#!/bin/sh
while read RIGA <&3
do
    echo $RIGA | tr a-z A-Z >&4
done

L'esempio seguente utilizza una funzione per la trasformazione dei dati, rendendo esplicita l'apertura e la chiusura dei descrittori:

#!/bin/sh
function elabora () {
    while read RIGA <&3
    do
        echo $RIGA | tr a-z A-Z >&4
    done
}
elabora 3< file_da_leggere 4> file_da_creare
3<&-
4<&-

L'esempio seguente non funziona, perché non c'è modo di aprire il descrittore in scrittura secondo la modalità che qui viene mostrata:

#!/bin/sh
3< file_da_leggere
4> file_da_creare    # Non funziona!
#
while read RIGA <&3
do
    echo $RIGA | tr a-z A-Z >&4
done
#
3<&-
4<&-

141.2.1   Gestione degli spazi

Il comando read interpreta il contenuto delle righe in base alla configurazione stabilita con la variabile di ambiente IFS. In pratica, per quanto riguarda gli esempi proposti e l'impostazione usuale di questa variabile, ciò significa che gli spazi orizzontali presenti all'inizio e alla fine delle righe, vengono eliminati.

Per evitare questo tipo di trattamento degli spazi occorrerebbe intervenire nella variabile di ambiente IFS, ma non è detto che il risultato che si ottiene sia corretto. Pertanto, conviene limitarsi all'uso «normale» del comando read, considerando la perdita degli spazi orizzontali iniziali e finali.

141.3   Contenuto senza file

Invece di aprire un file in lettura per fornirlo a un descrittore, è possibile inviare al descrittore direttamente il contenuto, attraverso il meccanismo noto come here document. Vengono messe a confronto le due forme:

n< file
n<< "marcatore_conclusivo"
    testo
    ...
marcatore_conclusivo

L'esempio seguente ne riprende uno già proposto in precedenza:

#!/bin/sh
function elabora () {
    while read RIGA <&3
    do
        echo $RIGA | tr a-z A-Z >&4
    done
}
elabora 4> file_da_creare 3<< "FINE_DEL_TESTO"
    bla bla bla bla bla
    bla bla bla bla bla
    bla bla bla bla bla
    bla bla bla bla bla
FINE_DEL_TESTO
3<&-
4<&-

Appunti di informatica libera 2007.02 --- Copyright © 2000-2007 Daniele Giacomini -- <daniele (ad) swlibero·org>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome shell_posix_accesso_ai_file.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico]

Valid ISO-HTML!

CSS validator!