Como obter o descritor de arquivo diferente de stdin stdout e stderr (para fazer algo como $ program 1file_1 3file_2)?

6

Quando um executável produz uma saída, prefiro deixar que o executável imprima a saída em stdout , a fim de redirecioná-la em um arquivo, bem como canalizá-la para outro comando.

Vamos supor que um executável tenha que gravar duas saídas distintas, geralmente redirecionadas para dois arquivos distintos. Eu gostaria de evitar passar os nomes de arquivos para o executável e escrever diretamente para arquivos, em vez disso eu gostaria de escrever algo como

$ program 1>file_1 3>file_2

É possível fazer algo assim?

    
por mox 15.07.2011 / 10:11

3 respostas

11

Você pode, mas não é uma boa ideia. Normalmente, os programas começam com três descritores de arquivos abertos:

  • 0 é a entrada padrão, em que os comandos que processam o texto de alguma forma lêem a entrada se ela não vier de um arquivo.
  • 1 é a saída padrão, para dados normais produzidos por um comando, se os dados não forem explicitamente indo para um arquivo.
  • 2 é um erro padrão, para mensagens de diagnóstico que não fazem parte dos dados úteis produzidos pelo comando.

Você pode violar essas convenções e usar mais descritores de arquivos, mas isso significa que seu aplicativo só poderá ser usado diretamente em um ambiente no qual o chamador especificou os descritores de arquivos corretos. Você não poderá testar facilmente isso em seu aplicativo: como os descritores de arquivo 3 e acima não são regulamentados, eles podem ser fechados quando o aplicativo é iniciado (isso pode ser detectado) ou podem estar abertos para algum propósito não relacionado. (isso não pode ser detectado).

A passagem de nomes de arquivos na linha de comando é a maneira normal de especificar vários arquivos de entrada ou saída.

Dito isso, para acessar descritores de arquivos arbitrários:

  • No shell: redirecionar para o número desejado, por exemplo,

    IFS= read -r line <&3
    printf "%s\n" "$line" >&4
    
  • Em C, chame read ou write com qualquer fd desejado ou chame fdopen para obter um fluxo stdio.
  • Em Perl, especifique um redirecionamento de shell como o nome do arquivo a ser aberto para duplicar um descritor de arquivo ou adicione = para fazer um fdopen simples.

    open IN3, "<&=3";
    open OUT4, ">&=4";
    
  • No Python, chame os.fdopen .
por 15.07.2011 / 20:40
3

Sim, você certamente pode. Nota 1>file_1 pode ser simplificado para >file_1 , pois 1 é o padrão.

Por exemplo:

$ cat test.ksh
#!/bin/ksh
echo "this goes to stdout" 
echo "this goes to stderr" >&2
echo "this goes to fd 3" >&3
$ ./test.ksh >file_1 3>file_2
this goes to stderr
$ cat file_1
this goes to stdout
$ cat file_2
this goes to fd 3
    
por 15.07.2011 / 12:56
1

Você pode redirecionar descritores de arquivos arbitrários no shell exatamente como o seu exemplo mostra. Programas que funcionam com vários fluxos precisam ser informados sobre os nomes dos arquivos a serem usados. Se você realmente quiser que o programa use um fd que você tenha redirecionado com o shell (talvez para um pipe), então passe /dev/fd/N para o nome do arquivo para que ele use fd N.

    
por 15.07.2011 / 21:03