Sto leggendo un libro sulla riga di comando di Linux in cui l'autore non sembra seguire le convenzioni nel manuale di bash per quanto riguarda i simboli delle frecce utilizzati nelle operazioni di reindirizzamento. Vale a dire, usa sempre la freccia sinistra <
nella duplicazione e chiusura dei descrittori di file indipendentemente dal fatto che i descrittori siano di input o di output.
Ecco un esempio:
exec 3<&0 4<&1 #shouldn't be 4>&1 ?
#...
exec 3<&- 4<&- #shouldn't be 4>&- ?
La pagina man di Bash è vaga a questo punto, in base ad essa, i descrittori di file di duplicazione/chiusura e spostamento hanno le seguenti sintassi:
#Duplicating and closing (in case word expands to -):
[n]<&word
[n]>&word
#Moving:
[n]<&digit-
[n]>&digit-
Sono descritti per avere un comportamento diverso solo se non forniamo esplicitamente il n
. Ma quando lo facciamo, significa che possiamo usare queste forme in modo intercambiabile?
Risposta accettata:
Non importa perché sia 4>&1
e 4<&1
fai la stessa cosa:dup2(1, 4)
che è la chiamata di sistema per duplicare un fd su un altro. L'FD duplicato eredita automaticamente la direzione I/O dell'FD originale. (lo stesso per 4>&-
rispetto a 4<&-
che entrambi risolvono in close(4)
e 4>&1-
che è il dup2(1, 4)
seguito da close(1)
).
Tuttavia, il 4<&1
la sintassi crea confusione a meno che per qualche motivo fd 1 non fosse esplicitamente aperto per la lettura (il che sarebbe ancora più confuso), quindi nella mia mente dovrebbe essere evitato.
Il duplicato fd
condivide la stessa descrizione del file aperto il che significa che condividono lo stesso offset nel file (per quei tipi di file in cui ha senso) e gli stessi flag associati (modalità di reindirizzamento/apertura I/O, O_APPEND e così via).
Su Linux, c'è un altro modo per duplicare un fd
(che in realtà non è una duplicazione) e crea una nuova descrizione del file aperto per la stessa risorsa ma con possibili flag diversi.
exec 3> /dev/fd/4
Mentre su Solaris e probabilmente la maggior parte degli altri Unice, è più o meno equivalente a dup2(4, 3)
, su Linux, che apre da zero la stessa risorsa indicata da fd 4.
Questa è una differenza importante, perché ad esempio, per un file normale, l'offset di fd 3 sarà 0 (l'inizio del file) e il file verrà troncato (motivo per cui ad esempio su Linux è necessario scrivere tee -a /dev/stderr
invece di tee /dev/stderr
).
E la modalità I/O può essere diversa.
È interessante notare che se fd 4 puntava all'estremità di lettura di una pipe, allora fd 3 ora punta all'estremità di scrittura (/dev/fd/3
si comporta come una pipe denominata ):
$ echo a+a | { echo a-a > /dev/fd/0; tr a b; }
b+b
b-b
$ echo a+a | { echo a-a >&0; tr a b; }
bash: echo: write error: Bad file descriptor
b+b