Cuando canalizo múltiples comandos de Unix como grep, sed, tr, etc., tiendo a especificar el archivo de entrada que se está procesando con cat. Entonces algo como cat file | grep ... | awk ... | sed ...
.
Pero recientemente, después de dejar un par de comentarios en mis respuestas que indicaban que este era un uso inútil del gato, pensé en hacer la pregunta aquí.
Busqué el tema y me encontré con el artículo de Wikipedia sobre UUOC y The Useless Use of Cat Award y me parece que los argumentos hechos son desde la perspectiva de la eficiencia.
La pregunta más cercana que encontré aquí fue esta: ¿Es un desperdicio llamar gato? - Pero no es exactamente lo que estoy preguntando.
Supongo que lo que sugiere el campo UUOC es usar cmd1 args < file | cmd2 args | cmd3 ..
o si el comando tiene una opción para leer del archivo y luego pasarlo como argumento.
Pero a mí me cat file | cmd1 ... | cmd2
parece mucho más fácil de leer y entender. No tengo que recordar diferentes formas de enviar archivos de entrada a diferentes comandos, y el proceso fluye lógicamente de izquierda a derecha. Primero entrada, luego el primer proceso ... y así sucesivamente.
¿No entiendo qué argumentos se hacen sobre el uso inútil del gato? Entiendo que si estoy ejecutando un trabajo cron que se ejecuta cada 2 segundos que procesa mucho, entonces en ese caso cat podría ser un desperdicio. Pero, de lo contrario, ¿cuál es el consenso general sobre el uso del gato?
fuente
< file cmd1 args | cmd2 args ...
también funciona ... así que su argumento de " izquierda a derecha " es nulo. A menudo lo uso para mayor claridad: el orden que mostré puede hacer que la gente haga una pausa, lo que no es bueno. Con un mayor número de hilos convirtiéndose en la norma, esto se está convirtiendo en un problema menor de la OMI ...Respuestas:
Es inútil en el sentido de que usarlo así no logra nada del otro, posiblemente las opciones más eficientes no pueden (es decir, producir resultados adecuados).
Pero
cat
es mucho más poderoso que solocat somefile
. Consulteman cat
o lea lo que escribí en esta respuesta . Pero si solo necesita absolutamente el contenido de un solo archivo, puede obtener alguna ventaja de rendimiento al no usarcat
para acceder al contenido del archivo.En cuanto a la legibilidad, esto depende de sus gustos personales. Me gusta
cat
incluir archivos en otros comandos por la misma razón, especialmente si los aspectos de rendimiento son insignificantes.También depende de lo que esté escribiendo. Si se trata de su propio shell y métodos de conveniencia para su máquina de escritorio, a nadie excepto a usted le importará. Si se topa con un caso en el que sería mejor buscar la siguiente herramienta en la cadena, y distribuir esto como un software de uso frecuente en algún sistema Linux mínimo en un enrutador de bajo rendimiento o dispositivo similar con límites reales en capacidad de procesamiento, eso es diferente. Siempre depende del contexto.
fuente
En el uso diario de la línea de comandos no es realmente muy diferente. Especialmente no notará ninguna diferencia de velocidad, ya que el tiempo en la CPU que se evita al no usar
cat
, su CPU simplemente estará inactiva. Incluso si está recorriendo cientos o miles (o incluso cientos de miles) de elementos con toda practicidad, no hará mucha diferencia, a menos que esté en un sistema muy cargado (Carga promedio / N CPU> 1).El lugar donde el caucho se encuentra con el camino consiste en formar buenos hábitos y desalentar los malos. Para arrastrar un cliché mohoso, el diablo está en los detalles. Y son detalles como este que separan lo mediocre de lo genial.
Es como mientras conduce un automóvil, ¿por qué girar a la izquierda cuando puede hacer tres derechos en su lugar? Por supuesto que puedes, y funciona perfectamente. Pero si entendiste el poder de los giros a la izquierda, entonces tres derechos parecen tontos.
No se trata de guardar un identificador de archivo, 17k de RAM y 0.004 segundos de tiempo de CPU. Se trata de toda la filosofía de usar UNIX. El "poder de los giros a la izquierda" en mi ilustración no es simplemente redireccionar la entrada, es la filosofía de UNIX. Completamente hacer esto, te hará sobresalir mucho mejor que los que te rodean, y obtendrás el respeto de aquellos que sí entienden.
fuente
cat
no eliminará ninguna paginación, aunque la conexión a algo podría eliminar la paginación de algunas aplicaciones.A menudo lo uso
cat file | myprogram
en ejemplos. A veces me acusan de uso inútil del gato ( http://www.iki.fi/era/unix/award.html ). No estoy de acuerdo por las siguientes razones:Es fácil entender lo que está pasando.
Al leer un comando UNIX, espera un comando seguido de argumentos seguidos de redirección. Que es posible poner en cualquier lugar de la redirección pero rara vez se ve - por lo tanto la gente tendrá más dificultades para leer el ejemplo. Yo creo
es más fácil de leer que
Si mueve la redirección al inicio, está confundiendo a las personas que no están acostumbradas a esta sintaxis:
y los ejemplos deberían ser fáciles de entender.
Es fácil de cambiar.
Si sabe que el programa puede leer de cat, normalmente puede suponer que puede leer la salida de cualquier programa que salga a STDOUT y, por lo tanto, puede adaptarlo a sus propias necesidades y obtener resultados predecibles.
Hace hincapié en que el programa no falla, si STDIN no es un archivo normal.
No es seguro asumir que si
program1 < foo
funcionacat foo | program1
, también funcionará. Sin embargo, es en la práctica seguro asumir lo contrario. Este programa funciona si STDIN es un archivo, pero falla si la entrada es una tubería, ya que utiliza la búsqueda:He mirado la penalización de rendimiento en http://oletange.blogspot.dk/2013/10/useless-use-of-cat.html La conclusión es no usar
cat file |
si la complejidad del procesamiento es similar a un simple grep y el rendimiento es más importante que la legibilidad. Para otras situacionescat file |
está bien.fuente
Creo que la posición de algunos de los que comentan que algo es un UUOC es que si uno realmente entiende la sintaxis de Unix y Shell, no usaría cat en ese contexto. Se ve como usar una gramática pobre: puedo escribir una oración usando una gramática pobre y aún así expresar mi punto de vista, pero también demuestro mi pobre comprensión del idioma y, por extensión, mi pobre educación. Entonces decir que algo es un UUOC es otra forma de decir que alguien no entiende lo que está haciendo.
En lo que respecta a la eficiencia, si está ejecutando una tubería desde la línea de comandos, la máquina tarda menos tiempo en ejecutarse
cat somefile |
que si usted piensa si podría ser más eficiente de usar< somefile
. Simplemente no importa.fuente
cat somefile | prog
en shell sin gato,prog < somefile
pero siempre parecían estar en el orden incorrecto para mí, particularmente con una cadena de comandos unidos. Ahora veo que algo tan elegante como< somefile prog
el truco, gracias. Me he quedado sin las excusas que me quedaban para usar cat.No estaba al tanto del premio hasta hoy, cuando un novato intentó ponerme el UUOC por una de mis respuestas. Fue a
cat file.txt | grep foo | cut ... | cut ...
. Le di una parte de mi mente, y solo después de hacerlo visité el enlace que me dio refiriéndome a los orígenes del premio y la práctica de hacerlo. Una búsqueda más profunda me llevó a esta pregunta. Desafortunadamente, a pesar de la consideración consciente, ninguna de las respuestas incluyó mi justificación.No quise ponerme a la defensiva cuando lo educaba. Después de todo, en mis años más jóvenes habría escrito el comando como
grep foo file.txt | cut ... | cut ...
porque cada vez que haces los solteros frecuentesgrep
aprendes la ubicación del argumento del archivo y es fácil saber que el primero es el patrón y los posteriores son los nombres de los archivos.Fue una elección consciente cuando respondí la pregunta con el
cat
prefijo en parte debido a una razón de "buen gusto" (en palabras de Linus Torvalds), pero principalmente por una razón de función convincente.La última razón es más importante, así que lo expondré primero. Cuando ofrezco una tubería como solución, espero que sea reutilizable. Es muy probable que una tubería se agregue al final o se empalme en otra tubería. En ese caso, tener un argumento de archivo para grep arruina la reutilización, y muy posiblemente lo haga en silencio sin un mensaje de error si el argumento del archivo existe. I. e.
grep foo xyz | grep bar xyz | wc
le dará cuántas líneasxyz
contienebar
mientras espera el número de líneas que contienen ambosfoo
ybar
. Tener que cambiar los argumentos a un comando en una tubería antes de usarlo es propenso a errores. Agregue a esto la posibilidad de fallas silenciosas y se convierte en una práctica particularmente insidiosa.La razón anterior tampoco es importante ya que una gran cantidad de "buen gusto" es simplemente una razón subconsciente intuitiva para cosas como las fallas silenciosas anteriores que no se puede pensar en el momento en que una persona necesitada de educación dice "pero no ese gato inútil ".
Sin embargo, trataré de hacer consciente también la razón anterior del "buen gusto" que mencioné. Esa razón tiene que ver con el espíritu de diseño ortogonal de Unix.
grep
no lo hacecut
yls
no lo hacegrep
. Por lo tanto, al menosgrep foo file1 file2 file3
va en contra del espíritu de diseño. La forma ortogonal de hacerlo escat file1 file2 file3 | grep foo
. Ahora,grep foo file1
es simplemente un caso especial degrep foo file1 file2 file3
, y si no lo trata de la misma manera, al menos está agotando los ciclos del reloj cerebral tratando de evitar el premio inútil del gato.Eso nos lleva al argumento de que
grep foo file1 file2 file3
es concatenante, y secat
concatena, por lo que es apropiado,cat file1 file2 file3
pero porquecat
no es concatenante,cat file1 | grep foo
por lo tanto, estamos violando el espíritu decat
Unix y del todopoderoso. Bueno, si ese fuera el caso, entonces Unix necesitaría un comando diferente para leer la salida de un archivo y escupirlo en stdout (no paginarlo ni nada simplemente un spit para stdout). Por lo tanto, tendría la situación en la que dicecat file1 file2
o dicedog file1
y recuerda concienzudamente evitarcat file1
evitar obtener el premio, al tiempo que evitadog file1 file2
que, con suerte, el diseñodog
arroje un error si se especifican varios archivos.Afortunadamente, en este punto, simpatiza con los diseñadores de Unix por no incluir un comando separado para escupir un archivo a stdout, mientras que también nombra
cat
para concatenar en lugar de darle otro nombre.<edit>
hay un perro así, el desafortunado<
operador. Es desafortunado su ubicación al final de la tubería, lo que impide su fácil componibilidad. No hay una forma sintáctica o estéticamente limpia de colocarlo al principio. También es desafortunado no ser lo suficientemente general, por lo que comienza con el perro pero simplemente agrega otro nombre de archivo si también desea que se procese después del anterior. (Por>
otro lado, no es la mitad de malo. Tiene una ubicación casi perfecta al final. Por lo general, no es una parte reutilizable de una tubería, y en consecuencia se distingue simbólicamente).</edit>
La siguiente pregunta es ¿por qué es importante tener comandos que simplemente escupen un archivo o la concatenación de varios archivos a stdout, sin ningún procesamiento adicional? Una razón es evitar tener todos los comandos de Unix que operan en la entrada estándar para saber cómo analizar al menos un argumento de archivo de línea de comando y usarlo como entrada si existe. La segunda razón es evitar que los usuarios tengan que recordar: (a) dónde van los argumentos del nombre de archivo; y (b) evite el error silencioso de la tubería como se mencionó anteriormente.
Eso nos lleva a por qué
grep
tiene la lógica extra. La razón es permitir la fluidez del usuario para los comandos que se usan con frecuencia y de forma independiente (en lugar de como una tubería). Es un ligero compromiso de ortogonalidad para una ganancia significativa en la usabilidad. No todos los comandos deben diseñarse de esta manera y los comandos que no se usan con frecuencia deben evitar por completo la lógica adicional de los argumentos del archivo (recuerde que la lógica adicional conduce a una fragilidad innecesaria (la posibilidad de un error)). La excepción es permitir argumentos de archivo como en el caso degrep
. (por cierto, tenga en cuenta quels
tiene una razón completamente diferente para no solo aceptar, sino que también requiere argumentos de archivo)Finalmente, lo que podría haberse hecho mejor es si comandos tan excepcionales como
grep
(pero no necesariamentels
) generan un error si la entrada estándar está disponible. Esto es razonable porque los comandos incluyen lógica que viola el espíritu ortogonal del todopoderoso Unix para comodidad del usuario. Para mayor comodidad del usuario, es decir, para evitar el sufrimiento causado por una falla silenciosa, tales comandos no deben dudar en violar su propia violación al alertar al usuario si existe la posibilidad de una falla silenciosa.fuente
grep pattern f1 f2 f3
no es una simple concatenación .grep
conoce archivos e imprime nombres de archivos (y opcionalmente números de línea y cualquier otra cosa).grep . /sys/kernel/mm/transparent_hugepage/*
es un buen truco para imprimir nombre de archivo: contenido de archivo con muchos archivos de una sola línea. El diseño clásico de Unix es que la mayoría de las utilidades funcionan*.txt
sin necesidadcat
.cat
es para aplanar múltiples archivos en una secuencia.grep
ejemplo con un programa comocut
ese no tiene ningún motivo para preocuparse por múltiples archivos, y siempre podría ser alimentado desde su stdin. Algunas utilidades, comotr
, no aceptan argumentos de archivos, y solo funcionan como un filtro, por lo que la elección es entrecat
y<
.<file cmd1 | cmd2 >out
No es maravilloso, lo admito, pero es totalmente posible acostumbrarse. Sigues hablando sobre "el espíritu del todopoderoso Unix" de una manera burlona, lo que me decepciona totalmente porque parece que no entiendes o no quieres entender la forma en que realmente pensaron los diseñadores de Unix. Está bien si no te gusta el diseño de Unix, pero no es inherentemente tonto. No estoy seguro de si el diseño del sistema operativo es anterior a la sintaxis de shell y cómo evolucionó todo, ¡perocat
valió la pena evitar un extra en 1970!cat
ayuda a reutilizar y empalmar tuberías, mientras que sin él puede obtener fallas silenciosas (busque "silenciosamente" en mi respuesta).En defensa de los usos inútiles del gato
(Algunos párrafos para ayudar a equilibrar el tsunami de comentarios persistentes en contra de esta práctica)
He estado usando bash durante muchos años tanto como shell y como lenguaje de script para guiones pequeños (y a veces lamentablemente para los no tan pequeños). Hace mucho, mucho tiempo, aprendí sobre el "Uso inútil del gato" (UUoC). Todavía soy culpable al menos cada semana, pero, francamente, rara vez me siento obligado a evitarlo. Creo que usar
cat
vs< file
tiene más que ver con el gusto que con las diferencias técnicas y escribí esta respuesta para proteger a las personas nuevas en Linux que comparten mi gusto porcat
de pensar que hay algo muy mal en su camino (y tenga en cuenta las pocas ocasiones en que hay). Al igual que Linus Torvalds, también creo que a menudo el gusto es más importante que la habilidad. Eso no significa que mi gusto sea mejor que el tuyo, pero sí significa que si algo sabe mal, no lo haré sin ganar algo digno.Ya es obvio que, al igual que el autor de la pregunta , siento que usar cat es muy natural cuando se trabaja en un REPL como bash donde estoy explorando un problema mediante la construcción incremental de comandos complejos. Aquí hay un ejemplo muy típico: tengo un archivo de texto y no sé mucho al respecto. Escribiré
cat file
para probar el contenido. Si la salida es demasiado Voy a golpear mi flecha hacia arriba y dependiendo de las circunstancias voy a añadir| head
o| grep foo
o| what_ever
extender mi orden anterior añadiendo las etapas de procesamiento. Esta forma de pasar gradualmente de un comando simple a uno más complejo al agregar un paso de procesamiento después del otro me parece muy natural (estoy haciendo lo mismo en ipython y me encanta la formapyfunctional
y herramientas de programación similares abarcan este estilo). Entonces, cuando trabajo en el bash shell, estoy seguro de que interrumpir mi flujo para eliminarlocat
es más inútil que dejarlo y sufrir ... bueno, no hay ninguna consecuencia en el 99.9% de los casos.Por supuesto, al escribir guiones las cosas pueden cambiar. Pero incluso cuando escribo guiones es mi opinión que las personas que se burlan de UUoC ignoran estas lecciones importantes por una gran mente: "La optimización prematura es la raíz de todo mal" . Y si no está haciendo algo atípico, es realmente difícil para UUoC ubicarse donde se necesitará la optimización. Por supuesto, definitivamente necesita saber qué es ineficiente (es la invocación de proceso adicional, por cierto, ya que pocos parecen mencionarlo). Tener ese conocimiento si trabaja en esos sistemas raros en los que invocar un proceso es costoso (por ejemplo, algunos sistemas integrados o CygWin en menor grado) sabrá qué hacer si una situación especial lo requiere. Por ejemplo, si te encuentras llamando
cat
muchas veces por segundo en un bucle (por cierto, si te encuentras en esa posición pregúntate si bash es la herramienta adecuada para el trabajo). Sin embargo, nuevamente: "primero haga que funcione correctamente y luego optimícelo si es necesario" .¿Y cómo explicas el tsunami de las quejas sobre UUoC Nick?
Además de que no todos tienen mi gusto, creo que una parte importante de por qué tanta gente se queja de UUoC no es técnica sino humana: la mayoría de los recién llegados a Unix no sabrán sobre el
< file command
idioma, por lo que es tentador para una persona más experimentada interpretar al "Viejo Gurú". " a ellos. También tendrá la oportunidad de usar palabras elegantes ("invocación de proceso") y tocar el tema querido de "optimización". Se garantiza una buena impresión, por lo que es muy difícil resistirse. Luego, los recién llegados tomarán el consejo del Gurú al pie de la letra y durante mucho tiempo lo repetirán a los demás como "La única verdad" (y votarán esta respuesta :-). Nota divertida: probablemente es tan fácil arreglar bash para evitar cualquier ineficiencia de UUoC que uno tiene que preguntarse por qué nadie agregó esta característica o hizo< filename
cat un archivo después de tantos años. Un alma oscura sugeriría que a algunos hackers de barba gris les gusta dejar oportunidades para burlarse de nosotros ;-)fuente
Lo que sería realmente agradable es un shell que admita sintaxis como:
Mientras tanto, creo que
cat filename | realcmd1...
es aceptable, ya que mantiene la sintaxis estandarizada con comandos iniciales que requieren el nombre de archivo como argumento.fuente
< filename cmd | cmd2 ...
. ¿Está lo suficientemente cerca?< file command ...
al menos desde mediados de los 80 y probablemente desde los 70 cuandosh
se escribió el original . En términos más generales, las redirecciones de E / S se analizan de izquierda a derecha y se pueden intercalar en cualquier orden dentro de la línea de comando. Entonces,cmd <file arg arg...
también sería válido.Para todos los que dicen que el gato es aceptable porque "huele" mejor o "es más legible", solo diría esto:
Quizás para usted ... pero no para otros que puedan leer o intentar comprender su código. Si nunca intentas instruir a otros con tus ejemplos o compartir tu código, entonces, por supuesto, úsalo a tu gusto.
También agregaré este comentario, como usuario de Linux y administrador / ingeniero desde hace mucho tiempo ... (y hay muchos de nosotros) hace que nuestros ojos sangren al ver esto. ¿Por qué? Porque utiliza recursos en sistemas en los que controlamos estrictamente los recursos. El comando cat y la propia tubería utilizan memoria adicional y identificadores de archivos que son completamente inútiles. Has vinculado recursos que mi sistema necesita gratis y no has obtenido NADA que pueda explicar el uso de estos recursos. Este es un gran no no.
Ahora puedo sentarme aquí y debatir cosas como el olor del código o la legibilidad todo el día con cualquiera, pero al final del día es cuestión de escribir o mal y cada vez que usas recursos en un sistema y no ganas nada por ello ... está mal.
Como usuario doméstico, puede aprender de mi consejo y aprender mejores formas de hacer las cosas o puede elegir cegarse por el "olor" de los gatos, su elección ... pero sepa que si usa abiertamente esta práctica, se le llamará en esta práctica todo el tiempo y silenciosamente tendrás que admitir que tienen razón y que eres terco porque es verdad. :-)
fuente
cat foo.txt | ...
. La otra respuesta explica bien por qué puede ser un buen uso. El resumen simple del caso a favor es: "$ CPU time << $ Brain time" (como comentó @MikeP arriba).