Si se le pide a un shell que ejecute un comando probablemente inútil ( o parcialmente inútil ) que se sabe que termina, como cat hugeregularfile.txt > /dev/null
, ¿puede omitir la ejecución de ese comando ( o ejecutar un equivalente más barato, por ejemplo touch -a hugeregularfile.txt
)?
En términos más generales, ¿es el shell similar a los compiladores de C en el sentido de que puede realizar cualquier transformación en el código fuente, siempre que el comportamiento observable externamente sea como si la máquina abstracta lo evaluara?
EDITAR
Nota Bene: Mi pregunta, como se planteó originalmente, tenía un título que preguntaba si el shell puede hacer estas optimizaciones, no si debería o incluso si existen implementaciones que puedan hacerlas. Me interesa más la teoría que la práctica, aunque ambas son bienvenidas.
cat
ting hace una gran diferencia. El shell puede llegar a saber que el archivo es un dispositivo, pero no necesita ser confiable.wc
, por ejemplo). Pero, que yo sepa, POSIX no toma posición en la optimización de shell; O lo hace?ksh
. Como si no dijeran un proceso separado sino un entorno de subshell para permitir optimizaciones de ahorro de fork.Respuestas:
No, eso sería una mala idea.
cat hugeregularfile.txt > /dev/null
ytouch -a hugeregularfile.txt
no son lo mismocat
leerá todo el archivo, incluso si redirige la salida a/dev/null
. Y leer todo el archivo puede ser exactamente lo que quieres. Por ejemplo, para almacenarlo en caché para que las lecturas posteriores sean significativamente más rápidas. El caparazón no puede conocer tu intención.Del mismo modo, un compilador de C nunca optimizará la lectura de un archivo, incluso si no mira las cosas que lee.
fuente
true
yfalse
) tiene efectos secundarios potenciales, y los efectos secundarios son casi siempre el punto de invocar el comando. El shell no podía conocer esos efectos secundarios de antemano (para programas externos comocat
) sin resolver el problema de detención. Entonces, con razón, no lo intenta, y asume que quisiste decir lo que dijiste.cat
. De hecho,cat
podría hacer cualquier cosa, desde formatear su disco duro hasta descargar Internet.true
yfalse
listo$?
.cat
y/dev/null
tienen significados típicos, pero no se garantiza que se comporten de esa manera. Para realizar optimizaciones sin garantizar ningún cambio en el comportamiento esperado, la optimización solo puede permitirse que implique construcciones implementadas dentro del propio shell y no elementos encontrados en el entorno de ejecución ... sin importar cuán intuitivos puedan parecer sus nombres.No, dado que
/dev/null
es solo un nombre, que podría usarse para cualquier otro dispositivo o para un archivo distinto de lo que "normalmente" es un sumidero de datos.Por lo tanto, un shell (o cualquier otro programa) no tiene idea, según el nombre, de si el archivo al que está escribiendo está haciendo algo "real" con los datos. Hay AFAIK y tampoco hay llamadas al sistema que el programa de shell puede hacer, para determinar que, por ejemplo, el descriptor de archivos no está haciendo nada.
Su comparación con la optimización del código ausente en un programa en C no funciona, ya que un shell no tiene la visión general total que un compilador de C tiene sobre un fragmento de código fuente. Un shell no sabe lo suficiente
/dev/null
para optimizar su ejemplo, más como un compilador de C no sabe lo suficiente sobre el código en una función a la que se vincula dinámicamente, para no hacer la llamada.fuente
/dev/null
especialmente, a veces. Una unidad incorporada que tiene su stdout dirigida/dev/null
, por ejemploecho foo >/dev/null
, no dará lugar a ninguna escritura/dev/null
. No hace nada especial si invoca un comando no integrado (comocat file >/dev/null
).cat
también podría ser otra cosa. Cualquier otra cosa, de hecho./dev/null
es uno de los muy pocos caminos estandarizados , junto con/dev/tty
,/dev/console
,/tmp
,/dev/
y/
.cat
es un ksh93 incorporado (no habilitado a menos que lo coloque/opt/ast/bin
antes/bin
(o dondecat
esté disponible)$PATH
). Y sí, aunquecat file > /dev/null
con eseread
contenido incorporadofile
, no lo escribe en / dev / null (aunque lo abre y lo establece).No optimizará los comandos en ejecución (y ya ha recibido una serie de buenas respuestas que le dicen por qué no debería), pero puede optimizar las horquillas, tuberías / pares de pares, lecturas en algunos casos. El tipo de optimizaciones que puede hacer:
trap
se hayan configurado algunos s. Por ejemplo, ensh -c ls
, la mayoría desh
las implementaciones (bash
,mksh
,ksh
,zsh
,yash
, algunas versiones deash
) no bifurcar un proceso para ejecuciónls
.ksh93
, la sustitución de comandos no creará una tubería o bifurcación de un proceso hasta que se llame a un comando externo ($(echo foo)
por ejemplo, se expandirá afoo
sin una tubería / par de conexiones o bifurcación).read
incorporación de algunos shells (bash
, AT&Tksh
) no realizará lecturas de un solo byte si detectan que el stdin es buscable (en cuyo caso harán lecturas grandes y buscarán hasta el final de lo que deben leer).fuente
ksh93
es el shell que lidera el camino en el frente de la optimización, ya que su objetivo es / debía verse a la par con lenguajes de programación comoperl
. Para que pueda consultar laksh
documentación, el código (buena suerte) y la lista de correo para obtener más información.sh -c 'ps -p "$$"'
que te daráps
y nosh
con esassh
implementaciones, o con strace / truss / tusc ...ksh -c 'ps; ps'
y bash -c 'ps; ps' es interesante. Ksh93 va más allá en su optimización.ksh
estamos hablando aquí.mksh
se comporta comobash
. Ese comportamiento está destinado principalmente a optimizar cosas comosystem("some command")
. Tenga en cuenta que hay un efecto secundario de esa optimización cuando se trata del estado de salida de los procesos terminados por una señal (en algunos shells).ksh93
solía tener un error ya que estaba haciendo la optimización incluso cuando se establecieron trampas.Al ver
cat hugeregularfile.txt > /dev/null
, el shell no puede creer que la acción es inútil,cat
no es parte del shell y podría hacer cualquier cosa en teoría, y también en la práctica.Por ejemplo, el usuario puede haber cambiado el nombre del ejecutable
rm
acat
, y de repente la línea realiza un comportamiento observable externamente, es decir, eliminando el archivo.El usuario puede haber compilado una versión
cat
que entra en un bucle infinito, por lo que el shell no puede asumir que se 'sabe que termina' como usted sugiere.Es posible que alguien haya instalado una versión
cat
que funcione según lo previsto, pero con un efecto secundario adicional de instalar un rootkit si alguna vez se ejecuta con los privilegios adecuados; nuevamente, el shell debería ejecutarlo debidamente.fuente
mksh
de hecho se optimizaV=$(cat file)
al convertirlo en un generador incorporado. Por lo tanto, el shell puede optimizarlo, pero no transformarlo en solo atouch -a
.cat
está incorporadomksh
, pero ese recurso recurre al sistemacat
si pasa alguna opción, por lo que con GNUcat
,mksh -c 'cat /dev/null --help'
no produce el mismo resultado quebash -c 'cat /dev/null --help'
, peromksh -c 'cat --help /dev/null'
le da lo mismo quebash -c 'cat --help /dev/null'
(ya que elmksh
gato incorporado analiza las opciones POSIX manera, mientras que GNU cat los analiza de la manera GNU).V=$(cat file)
se puede optimizar conV=$(< file)
. Esto acelera las cosas incluso sin una construccióncat
.