Como entender a ordenação do redirecionamento de saída? [duplicado]

10

Então, estou tentando aprender como passar o erro padrão e padrão para várias áreas.

Digamos que eu tenha uma pasta com here.txt sozinho.

Então, se eu fizer

ls here.txt not-here.txt  1>out  2>&1

Como here.txt está presente, terei alguma saída para direcionar para o arquivo out , mas como not-here.txt não está presente, um erro será enviado pelo erro padrão, que estou redirecionando para o padrão com 2>&1 .

No entanto, por que isso não funciona:

ls here.txt not-here.txt 2>&1 1>out

Parece funcionar apenas se eu fizer o redirecionamento após a instrução padrão? Por quê?

    
por Aruka J 24.09.2017 / 17:33

3 respostas

5

A ordem dos redirecionamentos é significativa . Por exemplo, o comando

ls > dirlist 2>&1

direciona a saída padrão e o erro padrão para o diretório do arquivo, enquanto o comando

ls 2>&1 > dirlist

direciona apenas a saída padrão para o arquivo dirlist, porque o erro padrão foi duplicado da saída padrão (normalmente ainda apontando para uma janela do terminal) antes que a saída padrão fosse redirecionada para o dirlist.

A princípio isso pode parecer contra-intuitivo, mas depois de pensar sobre isso, podemos entendê-lo.

Você encontra esta explicação em man bash , no capítulo sobre redirecionamento,

  

REDIRECÇÃO

     

Antes de um comando ser executado, sua entrada e saída podem ser redirecionadas usando uma notação especial interpretada pelo shell. O redirecionamento permite que os comandos de arquivos sejam duplicados, abertos, fechados, feitos para se referir a arquivos diferentes e podem alterar os arquivos dos quais o comando lê e grava. Redirecionamento também pode ser usado para modificar identificadores de arquivo no ambiente de execução do shell atual. Os seguintes operadores de redirecionamento podem preceder ou aparecer em qualquer lugar dentro de um comando simples ou podem seguir um comando. Os redirecionamentos são processados na ordem em que aparecem, da esquerda para a direita.

     

Cada redirecionamento que pode ser precedido por um número de descritor de arquivo pode ser precedido por uma palavra do formulário {varname} . Nesse caso, para cada operador de redirecionamento, exceto >&- e <&- , o shell alocará um descritor de arquivo maior ou igual a 10 e o atribuirá a varname . Se >&- ou <&- for precedido por {varname} , o valor de varname definirá o descritor de arquivo para fechar.

     

Nas seguintes descrições, se o número do descritor de arquivo for omitido e o primeiro caractere do operador de redirecionamento for < , o redirecionamento se referirá à entrada padrão (descritor de arquivo 0). Se o primeiro caractere do operador de redirecionamento for > , o redirecionamento se referirá à saída padrão (descritor de arquivo 1).

     

A palavra seguinte ao operador de redirecionamento nas descrições a seguir, a menos que seja indicado, é submetida à expansão de chave, expansão de til, expansão de parâmetro e variável, substituição de comando, expansão aritmética, remoção de cotação, expansão de nome de caminho e divisão de palavras. Se ele se expande para mais de uma palavra, o bash relata um erro.

     

Observe que a ordem dos redirecionamentos é significativa. Por exemplo, o comando

ls > dirlist 2>&1
     

direciona a saída padrão e o erro padrão para o arquivo dirlist , enquanto o comando

ls 2>&1 > dirlist
     

direciona apenas a saída padrão para o arquivo dirlist , porque o erro padrão foi duplicado da saída padrão antes que a saída padrão fosse redirecionada para dirlist .

Editar: as seguintes linhas de comando podem explicar o que acontece

Preparar

sudodus@xenial32:~$ touch qwerty;rm asdf
rm: cannot remove 'asdf': No such file or directory

Execute o comando list para um arquivo existente e um arquivo não existente

sudodus@xenial32:~$ ls qwerty asdf
ls: cannot access 'asdf': No such file or directory
qwerty

Redirecione a saída de erro antes de redirecionar a saída padrão. Apenas a saída padrão é redirecionada para o arquivo de saída.

sudodus@xenial32:~$ ls qwerty asdf 2>&1 > output-file ;echo '---';cat output-file 
ls: cannot access 'asdf': No such file or directory
---
qwerty

Redirecione a saída de erro após redirecionar a saída padrão. Tanto a saída de erro quanto a saída padrão são redirecionadas para o arquivo de saída.

sudodus@xenial32:~$ ls qwerty asdf > output-file 2>&1 ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty

O token &> pode ser usado para redirecionar o erro padrão e a saída padrão. Pode ser usado em bash , mas pode não estar disponível em outros shells.

sudodus@xenial32:~$ ls qwerty asdf &> output-file ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty
sudodus@xenial32:~$ 
    
por sudodus 24.09.2017 / 17:57
3
  • 2>x significa que o nome do arquivo x receberá os dados gravados no descritor 2 (também conhecido como stderr, erro padrão)
  • ... mas quando x é especificado como &1 , isso não significa "siga sempre 1 "; significa "copiar as propriedades atuais de 1 (e depois deixá-lo em paz)" .
  • Os redirecionamentos são aplicados na mesma ordem em que foram inseridos na linha de comando, mas antes que a execução real aconteça.

É por isso que 2>&1 1>whatever envia stderr para o terminal.

É por isso que find / -name mylostfile.txt 3>&1 1>&2 2>&3 | grep -v 'Permission denied' troca stderr e stderr, para que você possa filtrar algumas linhas comuns do stderr, mas ainda assim veja todas as stdout. (O descritor 3 aqui não é usado por programas).

    
por kubanczyk 24.09.2017 / 22:59
2

O shell encontra e define na ordem em que vê a coisa. No primeiro caso:

ls here.txt not-here.txt  1>out  2>&1

A saída é redirecionada e, em seguida, o erro padrão é enviado para o mesmo local.

No segundo caso,

ls here.txt not-here.txt 2>&1 1>out
Standardout out ainda está definido para o terminal, então o erro padrão é enviado para o terminal THEN out padrão é alterado. O shell já definiu o erro padrão.

    
por jpezz 24.09.2017 / 18:01