Onde colocar um redirecionamento de shell Bash para um comando? [duplicado]

3

Além do standalone exec >&2 para redirecionar a entrada e a saída do shell atual, existem algumas diferenças comportamentais nos seguintes comandos:

  1. echo -en "C\nB\nA\n" | sort 2>/dev/stdout >&2
  2. echo -en "C\nB\nA\n" 2>/dev/stdout >&2 | sort
  3. 2>/dev/stdout >&2 echo -en "C\nB\nA\n" | sort

Se os comandos acima foram equivalentes, qual é a variante preferida?

    
por Tim Friske 19.11.2012 / 01:34

2 respostas

3

Primeiro, em um comando simples (basicamente, o nome de um programa seguido por alguns argumentos), a posição relativa de argumentos e redirecionamentos não importa. Você pode até ter redirecionamentos antes do nome do comando. Os seguintes são todos equivalentes:

foo --bar qux >out 2>err
foo >out --bar 2>err
>out 2>err foo --bar qux

(Eu não vou listar todas as possibilidades.) É comum colocar os redirecionamentos no final, então você pode surpreender um futuro leitor se você não fizer isso. No entanto, é apenas uma questão de estilo. Há algum benefício em colocar redirecionamentos de entrada antes dos redirecionamentos de comando e saída, principalmente em pipelines, porque mantém a ordem de leitura idêntica à ordem de processamento:

<input.txt command1 | command2 | command3 >output.txt

(contraste command1 <input.txt | command2 … , que coloca a origem após a primeira etapa de processamento).

Nos comandos compostos, você precisa colocar os redirecionamentos no final; Por exemplo, nos snippets a seguir, você não pode colocar o redirecionamento em nenhum outro lugar:

while some_predicate; do some_action; done <in >out
{ command1; command2; } <in >out

Quando há vários redirecionamentos, o pedido é importante se eles se sobrepuserem, ou seja, se eles tiverem descritores de arquivos em comum. Consulte Ordem dos redirecionamentos

Em um pipeline, os redirecionamentos se aplicam a cada comando canalizado. Nos seus exemplos, os redirecionamentos se aplicam a (1) somente o comando sort , (2,3) o comando echo . Como explicado acima, (2) e (3) são equivalentes.

Em (2) e (3), a saída de echo acaba no mesmo lugar em que estava antes do redirecionamento. Se você tivesse escrito echo -en "C\nB\nA\n" >&2 | sort , não haveria saída para stdout a partir do comando no lado esquerdo do pipe, então sort veria um stdin vazio.

Você pode redirecionar a entrada ou a saída de um bloco de comandos, colocando-os entre chaves:

{ command1 | command2; } 2>error.log

Eu suponho que sua escolha de redirecionamentos foi apenas para fins de demonstração - 2>/dev/stdout >&2 é uma maneira complexa de escrever 2>&1 (redirecionar erro padrão (ou seja, fd 2) para onde quer que a saída padrão vá). / p>     

por 20.11.2012 / 01:20
2

1 é diferente de 2 e 3. 2 e 3 são idênticos.

Na versão 1, C\nB\nA\n é enviado para sort . O FD 2 de sort é mapeado de seu destino original ( STDERR ) para STDOUT e, em seguida, FD 1, que teria ido para STDOUT de qualquer forma, enviado para ... sort ' STDOUT novamente (bastante sem propósito).

Nas versões 2 e 3, a FD 2 de echo é mapeada de seu destino original ( STDERR ) para STDOUT e, em seguida, FD 1, que teria ido para STDOUT , enviado para echo STDOUT .

Funcionalmente, esses comandos só produzirão saída diferente se um dos comandos enviar algo para STDERR .

Na versão 1, se echo produzir algo para FD 2, irá para STDERR , mas em 2 e 3, irá para STDOUT (e, portanto, também será canalizado para sort ). Além disso, na versão 1, se sort enviar algo para FD 2, ele irá para STDOUT , enquanto nas versões 2 e 3, essa saída irá para STDERR .

Em termos da "variante preferencial", você realmente deve usar algo mais como isso (supondo que você queira que echo STDERR vá para sort ):

echo -en "C\nB\nA\n" 2>&1 | sort

Isso funciona porque o FD 1 já vai para STDOUT por padrão, basta ter o FD 2 copiando a descrição do arquivo para o seu descritor.

    
por 19.11.2012 / 01:40