Roteiro:
#!/bin/sh
#
# reads stdin/file and copies it to clipboard
# clears it after 30s
#
cat "${1:-/dev/stdin}" | timeout 30 xclip -i -selection clipboard -r -verbose &>/dev/null &
Posso ver que apenas stdin não funciona (com bash funciona em stdin/file).
PS verbose é usado para fazer com que o xclip não seja daemonizado.
Responder1
&>
é um bashismo, você terá que alterá-lo >/dev/null 2>&1
para shells POSIX
Responder2
[esta resposta é sobre pipelines assíncronos em scripts; para o &>
operador bash obsoleto e por que você deve sempre usá >output 2>&1
-lo, consultesintaxe obsoleta e obsoleta]
#! /bin/sh cat "${1:-/dev/stdin}" | ... &
Aqui você tem um pipeline rodando de forma assíncrona (porque finalizado por &
), iniciado a partir de um script, ou seja, a partir de um shell com o controle de job desabilitado.
De acordo compadrão:
command1 & [command2 & ... ]
A entrada padrão para uma lista assíncrona, antes de qualquer redirecionamento explícito ser executado, deve ser considerada atribuída a um arquivo que possui as mesmas propriedades de
/dev/null
.
O problema é que dash
, ksh
, mksh
, yash
, etc interpretam "lista assíncrona" como qualquer comando, incluindo um pipeline, e redirecionarão o stdin do primeiro comando de /dev/null
:
$ echo foo | dash -c 'cat | tr fo FO & echo DONE'
DONE
$ echo | dash -c 'readlink /proc/self/fd/0 | cat & echo DONE'
DONE
/dev/null
Mas bash
só irá interpretá-lo como "comando simples" e só irá redirecionar seu stdin /dev/null
quando fornãoparte de um pipeline:
$ echo foo | bash -c 'cat | tr fo FO & echo DONE'
DONE
FOO
$ echo | bash -c 'readlink /proc/self/fd/0 | cat & echo DONE'
DONE
pipe:[69872]
$ echo | bash -c 'readlink /proc/self/fd/0 & echo DONE'
DONE
/dev/null
$ bash -c 'cat | tr a A & echo DONE'
DONE
cat: -: Input/output error
zsh
irá redirecioná-lo apenas /dev/null
quando o stdin original for um tty, não quando for outro tipo de arquivo:
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/tty
/dev/null
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/zero
/dev/zero
Uma solução alternativa que funciona em todos os shells é duplicar o stdin em outro descritor de arquivo e redirecionar o stdin do primeiro comando dele:
#! /bin/sh
exec 3<"${1:-/dev/stdin}"
cat <&3 | timeout 30 xclip -i -selection clipboard -verbose -r >/dev/null 2>&1 &
Responder3
dash
posicionado como padrão POSIX. POSIX especificou apenas [n]>
redirecionamento. Mas bash
apresenta muitos recursos próprios. &>
é um deles e significa descritores de saída ( stderr
e stdout
).
Você deveria ler um artigo sobrebater e corrercompatibilidade.
Talvez você seja útilcheckbashismosutilitário que pode ajudar a encontrar bash
instruções específicas em seus scripts.