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.

catting 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/nullytouch -a hugeregularfile.txtno son lo mismocatleerá 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
trueyfalse) 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,catpodría hacer cualquier cosa, desde formatear su disco duro hasta descargar Internet.trueyfalselisto$?.caty/dev/nulltienen 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/nulles 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/nullpara 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/nullespecialmente, 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).cattambién podría ser otra cosa. Cualquier otra cosa, de hecho./dev/nulles uno de los muy pocos caminos estandarizados , junto con/dev/tty,/dev/console,/tmp,/dev/y/.cates un ksh93 incorporado (no habilitado a menos que lo coloque/opt/ast/binantes/bin(o dondecatesté disponible)$PATH). Y sí, aunquecat file > /dev/nullcon esereadcontenido 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:
trapse hayan configurado algunos s. Por ejemplo, ensh -c ls, la mayoría deshlas 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á afoosin una tubería / par de conexiones o bifurcación).readincorporació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
ksh93es 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 lakshdocumentación, el código (buena suerte) y la lista de correo para obtener más información.sh -c 'ps -p "$$"'que te darápsy noshcon esasshimplementaciones, 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.kshestamos hablando aquí.mkshse 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).ksh93solí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,catno 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
rmacat, y de repente la línea realiza un comportamiento observable externamente, es decir, eliminando el archivo.El usuario puede haber compilado una versión
catque 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
catque 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
mkshde 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.catestá incorporadomksh, pero ese recurso recurre al sistemacatsi 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 elmkshgato 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.