Significância dos símbolos de setas na duplicação / fechamento de descritores de arquivos sob o bash

3

Estou lendo um livro sobre a linha de comando do Linux, no qual o autor não parece seguir as convenções do manual bash sobre símbolos de setas usados em operações de redirecionamento. Ou seja, ele sempre usa a seta para a esquerda < na duplicação e fechamento de descritores de arquivos, independentemente de os descritores serem de entrada ou saída.

Aqui está um exemplo:

exec 3<&0 4<&1 #shouldn't be 4>&1 ?
#...
exec 3<&- 4<&- #shouldn't be 4>&- ?

A página man do Bash é vaga neste ponto, de acordo com ela, os descritores de arquivo de duplicação / fechamento e movimentação têm as seguintes sintaxes:

#Duplicating and closing (in case word expands to -):
[n]<&word 
[n]>&word

#Moving:
[n]<&digit-
[n]>&digit-

Eles são descritos como tendo comportamento diferente somente se não fornecermos explicitamente o n . Mas quando o fazemos, significa que podemos usar esses formulários de forma intercambiável?

    
por Quentin 16.02.2013 / 18:58

1 resposta

2

Não importa, porque 4>&1 e 4<&1 fazem a mesma coisa: dup2(1, 4) , que é a chamada do sistema para duplicar um fd em outro. O fd duplicado herda automaticamente a direção de E / S do fd original. (o mesmo para 4>&- vs 4<&- , ambos resolvidos para close(4) e 4>&1- , que é o dup2(1, 4) seguido por close(1) ).

No entanto, a sintaxe 4<&1 é confusa, a menos que, por algum motivo, o fd 1 estivesse explicitamente aberto para leitura (o que seria ainda mais confuso), portanto, em minha mente, deve ser evitado.

O fd duplicado compartilha a mesma descrição do arquivo aberto , o que significa que compartilham o mesmo deslocamento no arquivo (para os tipos de arquivo que fazem sentido) e os mesmos flags associados (redirecionamento de E / S / modo de abertura, O_APPEND e assim por diante).

No Linux, há outra maneira de duplicar um fd (que não é realmente uma duplicação) e criar uma nova descrição do arquivo aberto para o mesmo recurso, mas com possivelmente diferentes bandeiras.

exec 3> /dev/fd/4

Enquanto no Solaris e provavelmente na maioria dos outros Unices, isso é mais ou menos equivalente a dup2(4, 3) , no Linux, isso abre o mesmo recurso que o apontado pelo fd 4 a partir do zero.

Essa é uma diferença importante, porque, por exemplo, para um arquivo regular, o deslocamento de fd3 será 0 (o início do arquivo) e o arquivo será truncado (por isso, por exemplo, no Linux, você precisa escreva tee -a /dev/stderr em vez de tee /dev/stderr ).

E o modo de E / S pode ser diferente.

Curiosamente, se fd 4 apontou para o final de leitura de um pipe, então fd3 agora aponta para o fim da escrita ( /dev/fd/3 se comporta como um pipe nomeado ):

$ 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
    
por 17.02.2013 / 18:53