AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 515862
Accepted
Seninha
Seninha
Asked: 2019-04-28 04:48:06 +0800 CST2019-04-28 04:48:06 +0800 CST 2019-04-28 04:48:06 +0800 CST

Como fazer um pipeline aguardar o fim do arquivo ou parar após um erro?

  • 772

Eu tentei o seguinte comando depois de assistir a este vídeo sobre travessuras de tubos.

man -k . | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf | zathura -

Ele basicamente imprime uma lista de manpages no dmenu para o usuário selecionar um deles, então ele usa xargs para executar man -Tpdf %(imprimir para stdout um pdf da manpage git da entrada do xargs) e passar o pdf para um leitor de pdf (zathura ).

O problema é que (como você pode ver no vídeo) o leitor de pdf inicia antes mesmo de eu selecionar uma página de manual no dmenu. E se eu clicar em Esc e não selecionar nenhum, o leitor de pdf ainda estará aberto, não mostrando nenhum documento.

Como posso fazer com que o leitor de pdf (e qualquer outro comando em uma cadeia de pipe) seja executado apenas quando sua entrada atingir um final de arquivo ou quando receber uma entrada? Ou, alternativamente, como posso fazer uma cadeia de pipe parar depois que um dos comandos encadeados retornar um status de saída diferente de zero (para que, se o dmenu retornar um erro por não selecionar uma opção, os comandos a seguir não sejam executados)?

shell-script scripting
  • 3 3 respostas
  • 2131 Views

3 respostas

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2019-04-28T12:26:06+08:002019-04-28T12:26:06+08:00

    Como posso fazer com que o leitor de pdf (e qualquer outro comando em uma cadeia de pipe) seja executado apenas quando sua entrada atingir um final de arquivo ou quando receber uma entrada?

    Existe ifne(no Debian está no moreutilspacote):

    ifneexecuta o seguinte comando se e somente se a entrada padrão não estiver vazia.

    No seu caso:

    … | ifne zathura -
    
    • 13
  2. Kusalananda
    2019-04-28T05:10:31+08:002019-04-28T05:10:31+08:00

    Todos os comandos em um pipeline são iniciados praticamente ao mesmo tempo. É apenas a E/S sobre o tubo que os sincroniza. Além disso, um pipe só pode conter a quantidade de informações que o buffer do pipe permite.

    Portanto, você não pode evitar a execução de um estágio de um pipeline, porque

    1. o comando nesse estágio é iniciado assim que todos os outros estágios são iniciados de qualquer maneira, e
    2. se o comando não consumisse a entrada que chega pelo pipe, ele bloquearia os estágios anteriores do pipeline.

    Em vez disso, grave a saída em um arquivo enquanto deixa o pipeline terminar. Então use esse arquivo.

    Exemplo (como uma função que recebe um argumento):

    myman () {
        tmpfile=$( mktemp )
    
        if man -k "$1" | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf >"$tmpfile" && [ -s  "$tmpfile" ]
        then
            zathura "$tmpfile"
        fi
    
        rm -f "$tmpfile"
    }
    

    Além disso, isso não executaria o zathuraprograma se o pipeline falhar (a xargsparte retornou diferente de zero) ou o arquivo gerado estiver vazio.

    No bashshell, você também pode definir a pipefailopção de shell set -o pipefailpara que o pipeline retorne o status de saída do primeiro comando no pipeline que falha. E você gostaria de fazer a tmpfilevariável local:

    myman () {
        local tmpfile=$( mktemp )
    
        if [ -o pipefail ]; then
            set -o pipefail
            trap 'set +o pipefail' RETURN
        fi
    
        if man -k "$1" | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf >"$tmpfile"
        then
            zathura "$tmpfile"
        fi
    
        rm -f "$tmpfile"
    }
    

    Isso define a pipefailopção para a duração da função, se ainda não estiver definida, e a desativa, se necessário. Ele se livra do -steste no arquivo de saída.

    • 6
  3. mosvy
    2019-04-28T07:44:51+08:002019-04-28T07:44:51+08:00

    Arquivos PDF devem ser pesquisáveis; qualquer visualizador de pdf terá que olhar primeiro para o trailer e de lá pular para os deslocamentos da tabela xref.

    Como os pipes não são pesquisáveis, zathuraestá usando um truque de ofuscação, onde está copiando toda a entrada para um arquivo temporário e, em seguida, usa esse arquivo temporário normalmente. Esse tipo de truque "inteligente" está criando falsas esperanças e está levando as pessoas a supor que os arquivos pdf podem ser transmitidos.

    Mas de qualquer forma, realmentezathura espera o EOF antes de exibir o documento, você não precisa fazer nada para que isso aconteça:

    (sleep 10; cat file.pdf) | zathura -
    # will really show the content of file.pdf after 10 seconds
    

    O problema é que zathuranão tem opção de só abrir a janela se o arquivo estiver OK, e sair com erro se não for o caso -- ele vai ficar lá como se estivesse tudo OK:

    $ dd if=file.pdf bs=50000 count=1 status=none | zathura -
    error: could not open document  # its window still hanging around showing nothing
    
    $ echo $?
    0  # really?
    

    Portanto, mesmo que você esteja redirecionando a saída para um arquivo temporário e esteja executando apenas zathurase tudo estiver OK, não há garantia de que o usuário não será atendido com uma janela preta se zathuranão gostar da saída por um motivo ou outro .


    Por falar nisso,

    man -X man
    

    exibirá uma página de manual em uma janela X11 com gxditview, mesmo que pareça diretamente do '70 ;-)

    E, claro, você sempre pode usar:

    ... | xargs xterm -e man
    

    que, além de muitos outros aprimoramentos, permitirá o uso de expressões regulares em pesquisas e seleção de texto adequada.

    • 6

relate perguntas

  • Um script que imprime as linhas de um arquivo com seu comprimento [fechado]

  • Renomeie (acrescentar) arquivos CSV em massa com base em um valor dentro

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Dividir por delimitador e concatenar problema de string

  • MySQL Select com função IN () com array bash

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve