Guion:
#!/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 &
Puedo ver que solo la entrada estándar no funciona (con bash funciona en la entrada estándar/archivo).
PS detallado se utiliza para hacer que xclip no se demonice.
Respuesta1
&>
es un bashismo, tendrás que cambiarlo >/dev/null 2>&1
para shells POSIX
Respuesta2
[esta respuesta trata sobre canalizaciones asincrónicas en scripts; Para conocer el operador bash obsoleto &>
y por qué siempre debería usarlo >output 2>&1
en su lugar, consultesintaxis obsoleta y en desuso]
#! /bin/sh cat "${1:-/dev/stdin}" | ... &
Aquí tiene una canalización que se ejecuta de forma asincrónica (porque terminada por &
), iniciada desde un script, es decir, desde un shell con el control de trabajo deshabilitado.
De acuerdo con laestándar:
command1 & [command2 & ... ]
La entrada estándar para una lista asíncrona, antes de que se realicen redirecciones explícitas, se considerará asignada a un archivo que tenga las mismas propiedades que
/dev/null
.
El problema es que dash
, ksh
, mksh
, yash
, etc. interpretan la "lista asíncrona" como cualquier comando, incluida una canalización, y redirigirán la entrada estándar del primer comando desde /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
Pero bash
sólo lo interpretará como "comando simple" y sólo redirigirá su entrada estándar /dev/null
cuando esténoparte de una tubería:
$ 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
solo lo redireccionará /dev/null
cuando la entrada estándar original sea un tty, no cuando sea otro tipo de archivo:
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/tty
/dev/null
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/zero
/dev/zero
Una solución alternativa que funciona en todos los shells es duplicar la entrada estándar en otro descriptor de archivo y redirigir la entrada estándar del primer comando desde allí:
#! /bin/sh
exec 3<"${1:-/dev/stdin}"
cat <&3 | timeout 30 xclip -i -selection clipboard -verbose -r >/dev/null 2>&1 &
Respuesta3
dash
posicionado como estándar POSIX. POSIX solo especificó [n]>
la redirección. Pero bash
introduce muchas características propias. &>
es uno de ellos y significa descriptores de salida ( stderr
y stdout
).
Deberías leer el artículo sobregolpear y corrercompatibilidad.
Tal vez te resulte útilcheckbashismosutilidad que puede ayudar a encontrar bash
instrucciones específicas en sus scripts.