La siguiente ifnotemptyfunción canaliza su entrada al comando pasado como argumento, excepto que no hace nada si la entrada está vacía. Utilizarlo para tubería source --fooen sink --barpor escrito source --foo | pipe_if_not_empty sink --bar.
Esperaría que esta implementación funcione en todas las plataformas POSIX / Unix, aunque estrictamente hablando no cumple con los estándares: se basa en ddno leer más del byte que se le dice que lea en su entrada estándar.
Creo que head -c 1sería un reemplazo adecuado para dd bs=1 count=1 2>/dev/nullLinux.
Por otro lado, head -n 1no sería adecuado porque headnormalmente almacena su entrada y puede leer más de la línea que emite, y dado que está leyendo desde una tubería, los bytes adicionales simplemente se pierden.
read -r heade incluso read -r -n 1 headno son adecuados aquí porque si el primer carácter es una nueva línea, headse establecería en la cadena vacía, lo que hace imposible distinguir entre la entrada vacía y la entrada que comienza con una línea en blanco.
No podemos escribir simplemente head=$(head -c 1)porque si el primer carácter es una nueva línea, la sustitución de comandos eliminaría la nueva línea final, haciendo imposible distinguir entre la entrada vacía y la entrada que comienza con una línea en blanco.
En bash, ksh o zsh, puede reemplazar catpor </dev/stdinuna ganancia de rendimiento microscópico.
Si no le importa almacenar todos los datos intermedios en la memoria, aquí hay una implementación muy simple de pipe_if_not_empty.
Aquí hay una implementación un poco más simple con las siguientes advertencias:
Los datos producidos por la fuente se consideran vacíos si y solo si consisten únicamente en caracteres de nueva línea. (De hecho, esto puede ser deseable).
Los datos introducidos en el receptor terminan con exactamente un carácter de nueva línea, sin importar cuántas líneas nuevas terminen los datos producidos por la fuente. (Esto podría ser un problema).
Nuevamente, toda la información se almacena en la memoria.
$ 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
Es simple pero debería funcionar para usted. Si su "una función" envía una cadena vacía o incluso una nueva línea por la tubería, xargs -r, evitará el paso a "otra función".
ifne (1) de moreutils hace exactamente eso. Moreutils está disponible como paquete al menos en Debian y Ubuntu, probablemente también en otras distribuciones.
Esta función me falla cuando corro echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" [email protected]. Piensa eso liney hereson ambos destinatarios del correo electrónico, no tokens en el asunto. Tengo que escapar del "entorno del tema para que funcione. Sin embargo, la pipe_if_not_emptyfunción de la respuesta aceptada funciona para mí incluso sin escapar de nada.
kuzzooroo 05 de
2
Al menos algo como esto funciona:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
Tenga en cuenta que lo anterior considerará los saltos de línea y otros caracteres especiales como salida, por lo que una línea vacía que se pasa a esa instrucción if se considerará como una salida. Simplemente aumente el límite de -gt si su salida debería ser superior a 1 byte :)
Respuestas:
La siguiente
ifnotempty
función canaliza su entrada al comando pasado como argumento, excepto que no hace nada si la entrada está vacía. Utilizarlo para tuberíasource --foo
ensink --bar
por escritosource --foo | pipe_if_not_empty sink --bar
.Notas de Diseño:
dd
no leer más del byte que se le dice que lea en su entrada estándar.head -c 1
sería un reemplazo adecuado paradd bs=1 count=1 2>/dev/null
Linux.head -n 1
no sería adecuado porquehead
normalmente almacena su entrada y puede leer más de la línea que emite, y dado que está leyendo desde una tubería, los bytes adicionales simplemente se pierden.read -r head
e inclusoread -r -n 1 head
no son adecuados aquí porque si el primer carácter es una nueva línea,head
se establecería en la cadena vacía, lo que hace imposible distinguir entre la entrada vacía y la entrada que comienza con una línea en blanco.head=$(head -c 1)
porque si el primer carácter es una nueva línea, la sustitución de comandos eliminaría la nueva línea final, haciendo imposible distinguir entre la entrada vacía y la entrada que comienza con una línea en blanco.cat
por</dev/stdin
una ganancia de rendimiento microscópico.Si no le importa almacenar todos los datos intermedios en la memoria, aquí hay una implementación muy simple de
pipe_if_not_empty
.Aquí hay una implementación un poco más simple con las siguientes advertencias:
Nuevamente, toda la información se almacena en la memoria.
fuente
Esto debería funcionar para ti
Un ejemplo
Es simple pero debería funcionar para usted. Si su "una función" envía una cadena vacía o incluso una nueva línea por la tubería, xargs -r, evitará el paso a "otra función".
Referencia para xargs: http://www.oreillynet.com/linux/cmd/cmd.csp?path=x/xargs
fuente
ifne (1) de moreutils hace exactamente eso. Moreutils está disponible como paquete al menos en Debian y Ubuntu, probablemente también en otras distribuciones.
fuente
La siguiente función intenta leer el primer byte, y si tiene éxito, ese byte y los gatos se graban el resto. Debe ser eficiente y 100% portátil.
Casos de prueba:
fuente
echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" [email protected]
. Piensa esoline
yhere
son ambos destinatarios del correo electrónico, no tokens en el asunto. Tengo que escapar del"
entorno del tema para que funcione. Sin embargo, lapipe_if_not_empty
función de la respuesta aceptada funciona para mí incluso sin escapar de nada.Al menos algo como esto funciona:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
Tenga en cuenta que lo anterior considerará los saltos de línea y otros caracteres especiales como salida, por lo que una línea vacía que se pasa a esa instrucción if se considerará como una salida. Simplemente aumente el límite de -gt si su salida debería ser superior a 1 byte :)
fuente
yourothercommand
nunca ve la salida deyourcommand
.En lugar de
sender | receiver
:O podría hacerlo más general cambiándolo para aceptar el programa receptor como un argumento como en la respuesta de Gilles:
fuente