A ifnotemptyfunção a seguir canaliza sua entrada para o comando passado como argumento, exceto que ela não faz nada se a entrada estiver vazia. Use-o para tubo source --fooem sink --barpor escrito source --foo | pipe_if_not_empty sink --bar.
Eu esperaria que essa implementação funcionasse em todas as plataformas POSIX / Unix, embora, estritamente falando, não seja compatível com os padrões: ela depende de ddnão ler mais do que o byte solicitado para ler em sua entrada padrão.
Eu acho head -c 1que seria um substituto adequado para dd bs=1 count=1 2>/dev/nullno Linux.
Por outro lado, head -n 1 não seria adequado, porque headnormalmente armazena em buffer sua entrada e pode ler mais do que a linha que ela gera - e, como está lendo em um canal, os bytes extras são perdidos.
read -r head e até mesmo read -r -n 1 head não são adequados aqui porque, se o primeiro caractere for uma nova linha, headseria definido como a sequência vazia, impossibilitando a distinção entre entrada vazia e entrada iniciando com uma linha em branco.
Não podemos simplesmente escrever head=$(head -c 1) porque, se o primeiro caractere for uma nova linha, a substituição do comando removeria a nova linha final, tornando impossível distinguir entre entrada vazia e entrada começando com uma linha em branco.
No bash, ksh ou zsh, você pode substituir catpor </dev/stdinum ganho de desempenho microscópico.
Se você não se importa em armazenar todos os dados intermediários na memória, aqui está uma implementação muito mais simples pipe_if_not_empty.
Aqui está uma implementação um pouco mais simples com as seguintes advertências:
Os dados produzidos pela fonte são considerados vazios se e somente se consistirem apenas em caracteres de nova linha. (Isso pode ser de fato desejável.)
Os dados alimentados no coletor terminam com exatamente um caractere de nova linha, independentemente de quantas novas linhas os dados produzidos pela fonte terminam. (Isso pode ser um problema.)
Novamente, todos os dados são armazenados na memória.
$ echo -e "\n\n"| xargs -r ls
$ # No output. ls did not run.
$ echo -e "\n\n1"| xargs -r ls
ls: cannot access 1:No such file or directory
É simples, mas deve funcionar para você. Se a sua "uma função" envia uma string vazia ou até mesmo uma nova linha no pipeline, xargs -r, impedirá a passagem para "outra função".
ifne (1) da moreutils faz exatamente isso. Moreutils está disponível como um pacote pelo menos no Debian e Ubuntu, provavelmente em outras distribuições.
Esta função falha para mim quando executo echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" [email protected]. Ele pensa isso linee hereé ambos os destinatários do e-mail, não os tokens no assunto. Eu tenho que escapar do "assunto ao redor para fazê-lo funcionar. No entanto, a pipe_if_not_emptyfunção da resposta aceita funciona para mim mesmo sem escapar de nada.
precisa saber é o seguinte
2
Pelo menos algo assim funciona:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
Observe que o item acima considerará os feeds de linha e outros caracteres especiais como saída, portanto, uma linha vazia passou para essa instrução if será considerada como saída. Apenas aumente o limite -gt se sua saída normalmente for superior a 1 byte :)
Respostas:
A
ifnotempty
função a seguir canaliza sua entrada para o comando passado como argumento, exceto que ela não faz nada se a entrada estiver vazia. Use-o para tubosource --foo
emsink --bar
por escritosource --foo | pipe_if_not_empty sink --bar
.Notas de projeto:
dd
não ler mais do que o byte solicitado para ler em sua entrada padrão.head -c 1
que seria um substituto adequado paradd bs=1 count=1 2>/dev/null
no Linux.head -n 1
não seria adequado, porquehead
normalmente armazena em buffer sua entrada e pode ler mais do que a linha que ela gera - e, como está lendo em um canal, os bytes extras são perdidos.read -r head
e até mesmoread -r -n 1 head
não são adequados aqui porque, se o primeiro caractere for uma nova linha,head
seria definido como a sequência vazia, impossibilitando a distinção entre entrada vazia e entrada iniciando com uma linha em branco.head=$(head -c 1)
porque, se o primeiro caractere for uma nova linha, a substituição do comando removeria a nova linha final, tornando impossível distinguir entre entrada vazia e entrada começando com uma linha em branco.cat
por</dev/stdin
um ganho de desempenho microscópico.Se você não se importa em armazenar todos os dados intermediários na memória, aqui está uma implementação muito mais simples
pipe_if_not_empty
.Aqui está uma implementação um pouco mais simples com as seguintes advertências:
Novamente, todos os dados são armazenados na memória.
fonte
Isso deve funcionar para você
Um exemplo
É simples, mas deve funcionar para você. Se a sua "uma função" envia uma string vazia ou até mesmo uma nova linha no pipeline, xargs -r, impedirá a passagem para "outra função".
Referência para xargs: http://www.oreillynet.com/linux/cmd/cmd.csp?path=x/xargs
fonte
ifne (1) da moreutils faz exatamente isso. Moreutils está disponível como um pacote pelo menos no Debian e Ubuntu, provavelmente em outras distribuições.
fonte
A função abaixo tenta ler o 1º byte e, se for bem-sucedido, faz eco nesse byte e faz o resto dos gatos. Deve ser eficiente e 100% portátil.
Casos de teste:
fonte
echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" [email protected]
. Ele pensa issoline
ehere
é ambos os destinatários do e-mail, não os tokens no assunto. Eu tenho que escapar do"
assunto ao redor para fazê-lo funcionar. No entanto, apipe_if_not_empty
função da resposta aceita funciona para mim mesmo sem escapar de nada.Pelo menos algo assim funciona:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
Observe que o item acima considerará os feeds de linha e outros caracteres especiais como saída, portanto, uma linha vazia passou para essa instrução if será considerada como saída. Apenas aumente o limite -gt se sua saída normalmente for superior a 1 byte :)
fonte
yourothercommand
nunca vê a saída deyourcommand
.Em vez de
sender | receiver
:Ou você pode torná-lo mais geral, alterando-o para aceitar o programa receptor como argumento, como na resposta de Gilles:
fonte