Como canalizar dados de um comando para outro comando que permite apenas um arquivo como argumento?

3

Eu tenho alguns dados arbitrários como uma saída de um comando (por exemplo, um fragmento de dados binários colocados usando tail ). Eu quero alimentá-lo para outro comando / programa que permite apenas um arquivo como um argumento (por exemplo, rawtopng [filein] [fileout] ), não suporta argumento de traço ( - ) e não consigo criar um arquivo temporário entre eles. Como posso fazer isso no bash?

Alguma coisa como rawtopng <(tail myfile) fileout funciona?

    
por niutech 31.01.2016 / 01:27

3 respostas

3

A substituição do processo rawtopng <(tail myfile) fileout cria um canal (assim como tail myfile | rawtopng - fileout ) e passa um nome para o canal para o programa. No Linux, rawtopng verá um nome como /dev/fd/42 e, se consultar o tipo de arquivo, será informado que é um canal. Nenhuma gravação no sistema de arquivos é necessária (isso é um pipe anônimo, não um pipe nomeado). Você pode ter um vislumbre do que está acontecendo, executando um comando como ls -ld <(echo foo)

Isso funcionará? Depende do que o comando rawtopng requer (o que eu não sei, não estou familiarizado com esse comando). Se tudo o que fizer for lido no arquivo, tudo bem. Se precisar procurar no arquivo (ou seja, se não ler sua entrada linearmente do início ao fim), ou se precisar saber o tamanho da entrada antes de começar a funcionar, isso não funcionará. Em tais casos, você precisará de um arquivo temporário.

Se o comando precisar de entrada ou entrada procurada com um tamanho conhecido antecipadamente, então você não tem escolha, você precisa criar um arquivo temporário. Se você quiser evitar gravar em disco, pode organizar o arquivo em um sistema de arquivos tmpfs , se suas variantes Unix oferecerem isso (o Linux faz). Você pode usar o comando mktemp para criar um arquivo temporário:

tmp=$(TMPDIR=/tmp mktemp XXXXXXXXXXXX.raw)
rawtopng "$tmp" fileout
rm "$tmp"

Em zsh, a variante de substituição do processo rawtopng =(tail myfile) fileout cria um arquivo temporário e o remove assim que o comando é concluído.

Outro caso em que a substituição do processo não é suficiente é se o programa insiste em um arquivo com uma extensão específica. Nesse caso, criar um canal nomeado pode ajudar:

mkfifo /tmp/foo.raw
tail myfile >/tmp/foo.raw &
rawtopng /tmp/foo.raw fileout
rm /tmp/foo.raw
    
por 01.02.2016 / 00:29
2

Eu acho que você está no caminho certo! <(tail myfile) criará um Canal nomeado anônimo e será um tipo de Bash Substituição de processo .

Normalmente, isso passará /dev/fd/XX como o "nome do arquivo", que é uma interface do descritor de arquivo para o processo em execução.

A partir dos exemplos na documentação vinculada:

bash$ wc <(cat /usr/share/dict/linux.words)
 483523  483523 4992010 /dev/fd/63

Para ler um processo, use <(command) e, para gravar em um processo, use >(command) .

Você pode ler mais sobre a Substituição de Processos na Wikipedia também.

    
por 31.01.2016 / 03:58
0

Você pode criar um pipe nomeado.

Faça algo como mkfifo input para criar o canal.

Inicie o programa que você deseja ler a saída e redirecione a saída para o pipe, também conhecido como myprog > input

Em seguida, execute seu outro comando com a entrada como o arquivo.

Note que os tubos são um direcional. O programa poderá ler, mas não escrever.

    
por 31.01.2016 / 01:30