
Digamos que eu tenha um fluxo de entrada padrão deconteúdo do arquivoe um comando que espera umnome do arquivocomo argumento e quero executar esse comando em um arquivo composto pelo conteúdo do arquivo do fluxo de entrada padrão.
Por exemplo, em vez do comando
imageviewer mouse.jpg
Eu quero alguma linha mágica magic
que torne isso equivalente a
cat mouse.jpg | magic
Como seria isso magic
em zsh
ou bash
?
De preferência, eu gostaria que parecesse
cat mouse.jpg | submagic | xargs imageviewer
isto é, eu gostaria submagic
de criar um arquivo temporário a partir do fluxo de entrada padrão e gerar o nome do arquivo criado.
As linhas magic
ou submagic
devem ser pipelines de shell usando apenas comandos bash ou zsh, seus componentes internos, GNU coreutils e similares.
Esta é toda a questão. Abaixo estão apenas esclarecimentos e antecedentes porque as pessoas continuaram interpretando mal o que eu quis dizer.
Ok, então pensei ter deixado isso claro, mas parece que não: eurealmentequero ter um pipeline fazendo o equivalente a
imageviewer mouse.jpg
quecomeça exatamentecom cat mouse.jpg | …
. Ou seja, eurealmentequererexatamenteuma linha magic
ou submagic
algo assimexatamenteos pipelines acima funcionam – eu quis dizer minha pergunta literalmente.
Isso significa, em particular, que as seguintes soluções sugeridas não funcionarão:
- iniciando o pipeline com
tmpfile = $(mktemp); cat mouse.jpg | …
- reescrevendo-o como
imageviewer =(cat mouse.jpg)
- reescrevendo-o como
echo mouse.jpg | xargs imageviewer
- usando uma função ou um binário para resolvê-lo, digamos, definindo
function magic () { … }
Pode-se dizer que o que me interessa é se é possível escrever um alias alias magic='…'
ou alias submagic='…'
que um dos pipelines acima funcione e que a definição desses aliases contenha nada mais do que comandos bash ou zsh, GNU coreutils e similares - nada escrito por mim mesmo.
Outro comentário. Você pensa imageviewer
em ser feh
ou sxiv
algo assim.
Fundo. Esta pergunta surgiu quando tentei abrir vários arquivos de imagem anexados a um e-mail usando meu cliente de e-mail neomutt
. Neomutt se oferece para marcar arquivos anexados e, em seguida, canalizar o conteúdo do arquivo para uma linha de comando que você pode digitar. Portanto, aqui só posso fornecer uma linha de comando que execute algo em um determinado fluxo de entrada padrão. Foi daí que surgiu a pergunta. Mas não estou interessado no problema original, mas apenas nesta questão.
Responder1
Pelo bash
menos, com o uso de umsubstituição de processo:
utility <( some_other_utility )
Isso se apresentaria utility
com umnome do arquivo. Ao utility
abrir o arquivo e lê-lo, ele lerá a saída padrão de some_other_utility
.
Seu exemplo:
cat mouse.jpg | submagic | xargs imageviewer
Presumo que isso se destina a enviar onome do arquivo mouse.jpg
para imageviewer
, pois não faz sentido enviar o conteúdo de um arquivo JPEG por meio de xargs
.
Isso poderia ser feito através de apenas
echo 'mouse.jpg' | xargs imageviewer
ou
xargs imageviewer <<<'mouse.jpg'
em bash
.
O envio do conteúdo de mouse.jpg
to imageviewer
pode ser feito com
cat mouse.jpg | imageviewer /dev/stdin
ou, usando a substituição do processo, com
imageviewer <( cat mouse.jpg )
Usando um arquivo temporário:
tmpfile=$(mktemp)
cat mouse.jpg >"$tmpfile"
imageviewer "$tmpfile"
rm "$tmpfile"
Possivelmente,
tmpfile=$(mktemp)
cat mouse.jpg | { cat >"$tmpfile"; echo "$tmpfile"; } | xargs imageviewer
rm "$tmpfile"
Este pipeline depende do fato de que xargs
esperaria a execução imageviewer
até ler o nome do arquivo na parte intermediária do pipeline. O nome do arquivo não seria gerado pelo comando intermediário até que o arquivo temporário fosse criado.
Responder2
Após um esclarecimento submagic
na pergunta editei a resposta.
Você zsh
pode criar um arquivo temporário a partir da saída de um comando com a extensão =( ... )
. Em contraste com <( ... )
o qual pode usar um arquivo de dispositivo como /dev/fd...
ou um pipe nomeado, o formulário =( ... )
cria um arquivo temporário pesquisável. Verhttp://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution
Supondo que cat mouse.jpg
seja apenas um exemplo para qualquer comando que envie dados de imagem para stdout, você pode usar
imageviewer =(cat mouse.jpg)
Se você precisar que o arquivo temporário criado por zsh tenha uma extensão específica, você pode definir oTMPSUFFIX
variável especial):
(TMPSUFFIX=.jpg; imageviewer =(cat mouse.jpg))
segunda atualização
Se você insiste na sintaxe
cat mouse.jpg | submagic | xargs imageviewer
seria possível criar um script submagic
semelhante aos comandos já propostos na resposta de Kusalananda.
#! /bin/sh
# A fixed name allows multiple runs without creating lots of files and
# allows a simple script to remove the file afterwards.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE" && cat > "$TMPFILE" && echo "$TMPFILE"
Em contraste com mecanismos de shell como =( cat mouse.jpg )
este, não seriam removidos $TMPFILE
após a execução imageviewer
.
Se você puder executar um segundo script após a execução, imageviewer
isso poderá remover o arquivo se ele souber o nome.
Roteirosubmagic-cleanup
#! /bin/sh
# A fixed name allows a simple script for cleaning up.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE"
Então você poderia correr
cat mouse.jpg | submagic | xargs imageviewer
submagic-cleanup
Responder3
Para atender aos requisitos exatos da sua pergunta, você pode fazer:
cat mouse.jpg | { tf=$(mktemp); cat >"$tf"; echo "$tf"; } | xargs imageviewer