1. Un comando es una caja con tres bocas
Hasta ahora miramos los comandos desde afuera: qué opciones aceptan, qué hacen con los archivos. Para este bloque conviene mirarlos de otra manera, como los ve el sistema. Un programa en ejecución es una caja que recibe datos por un lado y entrega datos por otro.
Lo notable es lo que el programa no sabe. sort ordena las líneas que le llegan y escribe el resultado. No sabe si esas líneas vienen del teclado, de un archivo o de otro programa. No sabe si lo que escribe aparecerá en una pantalla, quedará guardado en el disco o será la entrada de un tercero. Lee de «su entrada» y escribe en «su salida», y nada más.
Esa ignorancia es deliberada, y es la clave de todo. Como ningún programa depende de dónde vienen sus datos ni adónde van, cualquiera de ellos se puede conectar con cualquier otro, con un archivo o con la terminal, sin modificarlo. Quien hace las conexiones es la shell.
2. Los tres canales estándar
Cada proceso nace con tres canales de comunicación ya abiertos, listos para usar:
| Canal | Nombre en inglés | Abreviatura | Número | Para qué se usa | Conectado por defecto a |
|---|---|---|---|---|---|
| Entrada estándar | standard input | stdin | 0 | Los datos que el programa debe procesar. | El teclado. |
| Salida estándar | standard output | stdout | 1 | Los resultados. | La pantalla. |
| Error estándar | standard error | stderr | 2 | Los mensajes de error y de aviso. | La pantalla. |
«Estándar» significa aquí «el que se usa si no se indica otro». Las abreviaturas stdin, stdout y stderr aparecen en toda la documentación y en casi todos los lenguajes de programación, porque el modelo salió de Unix y fue adoptado en todas partes.
3. Los descriptores 0, 1 y 2
Los números de la tabla no son una convención de este curso. Son la forma en que el kernel identifica cada canal.
Un descriptor de archivo es un número entero con el que un proceso se refiere a un archivo, o a cualquier otra cosa que se pueda leer o escribir, que tiene abierto. Cada proceso tiene su propia tabla de descriptores.
Cuando un programa abre un archivo, el kernel le entrega un número: el primero que tenga libre. A partir de ahí, el programa lee y escribe indicando ese número. Los tres primeros están reservados por costumbre universal, y todo proceso los recibe ya abiertos al nacer:
| Descriptor | Canal | El programa lo usa para |
|---|---|---|
0 | Entrada estándar | Leer. |
1 | Salida estándar | Escribir resultados. |
2 | Error estándar | Escribir mensajes. |
3 en adelante | — | Los archivos que el propio programa abra. |
Esto explica una escritura que usamos desde el tema 10. En 2>/dev/null, el 2 es el descriptor: «el canal número 2, envíalo a…». Los operadores de redirección se refieren a los canales por su número.
En el tema 8 vimos que /proc expone los datos de cada proceso. Entre ellos está su tabla de descriptores, que se puede listar:
$ ls -l /proc/self/fd
total 0
lrwx------ 1 ana ana 64 oct 12 19:10 0 -> /dev/pts/0
lrwx------ 1 ana ana 64 oct 12 19:10 1 -> /dev/pts/0
lrwx------ 1 ana ana 64 oct 12 19:10 2 -> /dev/pts/0
lr-x------ 1 ana ana 64 oct 12 19:10 3 -> /proc/5321/fd
Es la tabla del propio ls, que al leer /proc/self se mira a sí mismo. Tiene cuatro descriptores. Los tres estándar apuntan a /dev/pts/0; el cuarto, el 3, es el directorio que ls abrió para listarlo, y es el primero que el programa pidió por su cuenta.
4. Por defecto, la terminal
El listado anterior muestra a qué están conectados los canales cuando no se indica nada: los tres al mismo archivo, /dev/pts/0. Es el archivo de dispositivo de la terminal, como informa el comando tty:
$ tty
/dev/pts/0
Un solo archivo sirve para todo porque una terminal es un dispositivo de dos direcciones. Leer de él entrega lo que se escribe en el teclado; escribir en él hace aparecer texto en la ventana. «Teclado» y «pantalla» son las dos caras del mismo archivo.
De aquí sale una observación que conviene retener: los canales no se inventan para cada comando. La shell tiene los suyos, conectados a la terminal desde que se abrió la ventana, y cada comando que lanza los hereda, igual que hereda la identidad y el directorio de trabajo. Por eso la salida de ls aparece en la misma ventana en que escribiste.
El sistema ofrece además tres nombres fijos para referirse a los canales del proceso que los usa, útiles cuando un programa exige un nombre de archivo:
$ ls -l /dev/stdin /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 oct 12 09:02 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 oct 12 09:02 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 oct 12 09:02 /dev/stdout -> /proc/self/fd/1
Son enlaces simbólicos, de los que estudiamos en el tema 14, hacia los descriptores 0, 1 y 2.
5. La salida y los errores son dos canales
En la pantalla, los resultados y los errores de un comando aparecen juntos, y nada indica cuál es cuál. Para comprobar que viajan por canales distintos hay que separarlos. Lo hacemos con un comando que produce las dos cosas a la vez: listar un archivo que existe y otro que no.
$ cd ~/practica
$ ls notas.txt nada.txt
ls: cannot access 'nada.txt': No such file or directory
notas.txt
Dos líneas, mezcladas en la pantalla. Ahora descartamos uno de los canales por vez, enviándolo a /dev/null, el sumidero del tema 8:
$ ls notas.txt nada.txt > /dev/null # descartar el canal 1
ls: cannot access 'nada.txt': No such file or directory
$ ls notas.txt nada.txt 2> /dev/null # descartar el canal 2
notas.txt
$ ls notas.txt nada.txt > /dev/null 2> /dev/null # descartar los dos
$ echo $?
2
| Se descartó | Quedó en la pantalla | Entonces… |
|---|---|---|
| El canal 1 | El mensaje de error. | El mensaje no viajaba por el canal 1. |
| El canal 2 | El nombre del archivo. | El resultado no viajaba por el canal 2. |
| Los dos | Nada. | No hay un tercer canal de salida. |
La demostración es completa. El signo > solo, sin número, se refiere al canal 1; es una abreviatura de 1>. Los operadores los estudiamos en detalle en el tema siguiente.
El último comando deja ver algo más: con las dos salidas silenciadas, el fallo sigue siendo detectable por el código de salida, que vale 2. Volvemos sobre eso en la sección 14.
6. Por qué los errores van aparte
Tener dos canales de salida parece una complicación. Se entiende con un caso en que la salida no va a la pantalla:
$ ls notas.txt nada.txt | wc -l
ls: cannot access 'nada.txt': No such file or directory
1
La salida de ls se envió a wc -l, para contar las líneas. El resultado es 1: hay un archivo. El mensaje de error no fue contado, y además llegó a la pantalla, donde alguien puede leerlo. Si los errores viajaran por el mismo canal que los resultados, habrían ocurrido dos cosas malas:
| Con un solo canal… | Consecuencia |
|---|---|
El mensaje de error entraría a wc, mezclado con los datos. | El resultado sería 2, un número equivocado, sin ninguna señal de que algo anduvo mal. |
| El mensaje no aparecería en la pantalla. | Nadie se enteraría del error. |
Esa es la razón del diseño, y la dio la experiencia: en las primeras versiones de Unix había un solo canal de salida, y los mensajes de error terminaban dentro de los archivos y de los documentos que se enviaban a imprimir. El segundo canal se agregó para corregirlo.
El principio es que los datos y los comentarios sobre los datos no deben mezclarse. El canal 1 lleva información para ser procesada por quien siga; el canal 2, información para la persona que opera.
7. Qué se escribe en cada canal
La separación no es solo entre «lo que salió bien» y «lo que salió mal». Por el canal de errores viaja todo lo que no es el resultado propiamente dicho:
| Va a la salida estándar (1) | Va al error estándar (2) |
|---|---|
| El resultado del comando: el listado, el texto filtrado, el número contado. | Los mensajes de error. |
| Lo que tiene sentido guardar en un archivo o pasar a otro programa. | Los avisos, aunque no impidan continuar. |
El texto de --help, cuando se lo pide. | Los indicadores de progreso y las barras de avance. |
Las preguntas al usuario, como las de rm -i. | |
| El mensaje de uso, cuando el comando se invocó mal. |
Varios casos de temas anteriores encajan aquí. Los Permission denied de find, que no eran fallas de la búsqueda: iban por el canal 2, y por eso 2>/dev/null los quitaba sin afectar los resultados. El aviso Removing leading '/' de tar. La pregunta overwrite? de cp -i, que tiene que llegar a la pantalla aunque la salida esté redirigida.
La diferencia entre las dos últimas filas de cada columna es instructiva. El mismo texto de ayuda va al canal 1 si lo pediste con --help, porque entonces es el resultado; y al canal 2 si apareció porque te equivocaste, porque entonces es un error.
Un programa bien escrito respeta esta disciplina, y vale la pena recordarla para cuando escribas los tuyos: es lo que hace que se puedan combinar con otros.
8. La entrada estándar
El canal 0 es el que más se pasa por alto, porque en el uso habitual no se nota. Casi todos los comandos de texto pueden recibir sus datos de dos maneras:
| Se invoca | Lee los datos de |
|---|---|
wc -l notas.txt | El archivo indicado. |
wc -l | La entrada estándar. |
Sin un archivo como argumento, el programa lee del canal 0, que por defecto es el teclado. Lo encontramos de paso en el tema 3, con cat. Se ve mejor con un comando que procesa lo que recibe:
$ sort
pera
manzana
uva
[Ctrl+D]
manzana
pera
uva
Tras ejecutar sort no aparece el indicador: el programa está esperando datos. Cada línea que se escribe le llega al pulsar Enter. Cuando se le indica que no hay más, con Ctrl+D, ordena lo recibido y lo escribe en su salida. Luego termina, y vuelve el indicador.
Nadie usa sort así, tecleando los datos. El ejemplo importa por lo que revela: sort no tiene un «modo teclado» y un «modo archivo». Tiene una entrada. Lo que hoy es el teclado, mañana será un archivo o la salida de otro comando, y sort hará lo mismo sin enterarse del cambio.
9. El fin de la entrada: Ctrl+D
Un programa que lee de un archivo sabe cuándo terminar: cuando el archivo se acaba. Con el teclado no hay un final natural, y hace falta una manera de señalarlo.
El fin de archivo, o EOF (end of file), es la condición que indica a un programa que no hay más datos que leer en un canal. Desde el teclado se produce pulsando Ctrl+D al comienzo de una línea.
Ctrl+D no envía un carácter al programa: le dice a la terminal «entrega lo que haya y, si no hay nada, avisa que la entrada terminó». El programa recibe ese aviso, completa su trabajo y termina de manera normal.
Eso lo distingue de la otra combinación que conocemos, y la diferencia es importante:
| Ctrl+D | Ctrl+C | |
|---|---|---|
| Significa | «No hay más datos.» | «Detente ahora.» |
| El programa | Termina su trabajo con lo recibido y sale normalmente. | Es interrumpido, sin terminar. |
| El resultado | Se produce. | Se pierde. |
| Código de salida | 0, si todo fue bien. | 130. |
En el ejemplo de sort, Ctrl+D produce la lista ordenada; Ctrl+C la habría descartado. Con wc -l, Ctrl+D da la cuenta de líneas, y Ctrl+C, nada.
Y aquí se explica algo del tema 2, donde dijimos que Ctrl+D cierra la terminal. No hay una regla especial: la shell es un programa que lee comandos de su entrada estándar. Al recibir el fin de archivo entiende que no llegarán más, y termina, como cualquier otro.
10. Cuando un comando parece colgado
La consecuencia práctica más frecuente de lo anterior es un susto. Se escribe un comando, se pulsa Enter, y no pasa nada: ni resultado, ni error, ni indicador. La causa suele ser que se olvidó el nombre del archivo, y el comando está leyendo del teclado.
$ grep pan # faltó el archivo: grep espera datos del teclado
▌
No está colgado ni consume recursos: espera, con toda paciencia, a que alguien escriba. Es el mismo estado que el del indicador > del tema 5, pero sin señal alguna. Reconocerlo ahorra muchos minutos:
| Síntoma | Causa probable | Salida |
|---|---|---|
| El cursor queda en una línea vacía, sin indicador. | El comando lee de la entrada estándar. | Ctrl+C para cancelar, o Ctrl+D para decirle que no hay datos. |
Aparece un indicador >. | La shell espera que se complete la línea: falta una comilla. | Ctrl+C. |
| El cursor no responde a ninguna tecla. | Se pulsó Ctrl+S. | Ctrl+Q. |
Los comandos que caen en esta situación son los que procesan texto: cat, grep, sort, wc, head, tail, sed, awk. Todos esperan un archivo o, en su defecto, la entrada.
11. Filtros, fuentes y sumideros
No todos los comandos usan los tres canales. Según cuáles usen, cumplen papeles distintos, y esa clasificación es la que permite saber de antemano cómo se pueden combinar:
| Papel | Lee de la entrada | Escribe en la salida | Ejemplos |
|---|---|---|---|
| Fuente: produce datos | No | Sí | ls, echo, date, find, ps, history, cat archivo |
| Filtro: transforma datos | Sí | Sí | sort, grep, head, tail, wc, cut, tr, sed, awk |
| Sumidero: consume datos | Sí | No, o no para seguir | less, que los muestra; una impresora; un programa que envía un correo |
| Ninguno: actúa sobre archivos | No | No | cp, mv, rm, mkdir, chmod, cd |
Un filtro es un programa que lee texto de su entrada estándar, lo transforma y escribe el resultado en su salida estándar.
Los filtros son los protagonistas de este bloque y del siguiente. Cada uno hace una transformación sencilla —ordenar, seleccionar, contar, recortar— y se encadenan porque la salida de uno tiene la forma que espera la entrada del otro: líneas de texto.
La última fila es una advertencia útil. A un comando que no lee su entrada no sirve de nada enviársela:
$ echo "notas.txt" | ls -l # ls no lee su entrada: lista el directorio, como siempre
total 28
drwxrwxr-x 2 ana ana 4096 oct 12 10:40 fotos
…
ls recibe sus nombres como argumentos, no por la entrada, e ignoró lo que le llegaba. Convertir líneas de entrada en argumentos es tarea de otro comando, xargs, que vemos en el tema 24.
12. Leer un archivo o leer la entrada
Para un filtro, las dos formas de la sección 8 dan el mismo resultado, con una diferencia pequeña que confirma todo el modelo:
$ wc -l notas.txt # el archivo, como argumento
1 notas.txt
$ wc -l < notas.txt # el archivo, conectado a la entrada
1
wc -l notas.txt | wc -l < notas.txt | |
|---|---|---|
| Quién abre el archivo | wc | La shell |
Qué recibe wc | Un argumento: el nombre | Ningún argumento; datos por el canal 0 |
Sabe wc el nombre | Sí, y lo muestra | No |
En el segundo caso, wc no puede mostrar el nombre porque nunca lo supo. Recibió un canal del que leer, ya conectado, y eso es todo. Lo notamos en el tema 12 sin poder explicarlo.
Hay comandos que solo leen su entrada y no aceptan archivos. Y hay una convención para pedir la entrada de manera explícita donde se espera un nombre de archivo: el guion solo, -, que presentamos en el tema 3. cat encabezado.txt - pie.txt escribe el primer archivo, luego lo que llegue por la entrada, luego el segundo.
13. Quién conecta los canales
Queda decir quién decide adónde va cada canal. La respuesta ya apareció dos veces en el tema: la shell, antes de ejecutar el comando.
Es el mismo esquema que vimos con la expansión, en el tema 9. Allí la shell reescribía la línea; aquí prepara las conexiones. En los dos casos, cuando el programa arranca el trabajo ya está hecho, y el programa no sabe que ocurrió.
- Lee la línea y reconoce los operadores:
>,<,|. shell - Abre los archivos indicados, o crea las tuberías. shell
- Crea el proceso y coloca en sus descriptores 0, 1 y 2 lo que corresponde. shell
- Quita los operadores de la línea: no se pasan como argumentos. shell
- El programa se ejecuta, lee del 0 y escribe en el 1 y en el 2, como siempre. comando
De este orden salen tres consecuencias que ya encontramos, cada una en su momento, como rarezas:
| Hecho | Explicación | Visto en |
|---|---|---|
sudo echo x > /etc/archivo falla. | El archivo lo abre la shell, con tu identidad, en el paso 2. sudo todavía no se ejecutó. | Tema 19 |
| Si el archivo de salida no se puede crear, el comando no se ejecuta. | La falla ocurre en el paso 2, antes del paso 5. | — |
ls cambia de formato cuando su salida no es la pantalla. | El programa puede preguntar si su canal 1 es una terminal, y adaptarse. | Tema 7 |
La tercera merece una aclaración, porque matiza lo dicho en la sección 1. Un programa no sabe adónde va su salida, pero sí puede averiguar si es una terminal. Unos cuantos lo aprovechan para ser más amables con las personas: columnas y colores en ls, colores en grep, barras de progreso. Cuando la salida va a un archivo o a otro programa, escriben texto simple, que es lo que conviene procesar.
14. Las cuatro vías de un comando
Con este tema se completa el cuadro de cómo se comunica un comando con el exterior. Son cuatro vías, y cada una tiene su propósito:
| Vía | Dirección | Lleva | Visto en |
|---|---|---|---|
| Argumentos | Hacia el comando | Qué hacer y sobre qué: opciones y nombres. | Tema 3 |
| Entrada estándar | Hacia el comando | Los datos a procesar. | Este |
| Salida y error estándar | Desde el comando | Los resultados, y los mensajes. | Este |
| Código de salida | Desde el comando | Un número: si tuvo éxito. | Tema 3 |
El código de salida funciona como un cuarto canal, mínimo, que no lleva texto sino un veredicto. Complementa a los otros: un programa escribe en el canal 2 qué salió mal, para una persona, y devuelve un número distinto de cero para que otro programa sepa que algo salió mal. En la sección 5 lo vimos sobrevivir al silenciamiento de las dos salidas. Sobre él se construye el encadenamiento de comandos del tema 25.
El bloque desarrolla cada conexión posible de estos canales:
| Tema | Conecta los canales con… | Operadores |
|---|---|---|
| 22, este | La terminal: el caso por defecto. | — |
| 23 | Archivos. | >, >>, <, 2>, 2>&1 |
| 24 | Otros comandos. | | |
| 25 | Los resultados de un comando con la ejecución de otro. | ;, &&, ||, $( ) |
Y la referencia del tema:
| Concepto | Detalle |
|---|---|
Entrada estándar, stdin | Descriptor 0. Por defecto, el teclado. |
Salida estándar, stdout | Descriptor 1. Por defecto, la pantalla. |
Error estándar, stderr | Descriptor 2. Por defecto, la pantalla. |
| Ctrl+D | Fin de la entrada. El programa termina normalmente. |
| Ctrl+C | Interrupción. El programa no termina su trabajo. |
ls -l /proc/self/fd | Muestra a qué está conectado cada descriptor. |
tty | Muestra el archivo de dispositivo de la terminal. |
En el tema 23 usamos el modelo: conectamos cada uno de los tres canales a un archivo, por separado y juntos, y vemos todas las formas de hacerlo.
15. Resumen
- Un programa lee de su entrada y escribe en su salida, sin saber de dónde vienen los datos ni adónde van. Esa independencia es lo que permite combinarlos.
- Todo proceso nace con tres canales abiertos: la entrada estándar, la salida estándar y el error estándar.
- El kernel los identifica con los descriptores de archivo 0, 1 y 2. Los números mayores corresponden a los archivos que el programa abre por su cuenta.
- Por defecto los tres están conectados a la terminal: la entrada es el teclado y las dos salidas son la pantalla. Los comandos los heredan de la shell.
- La salida y los errores son canales distintos, aunque en la pantalla aparezcan mezclados. Se comprueba descartando uno por vez.
- Los errores van aparte para no contaminar los datos que procesa el comando siguiente, y para seguir llegando a la persona que opera.
- Por el canal 1 viajan los resultados; por el 2, los errores, los avisos, el progreso y las preguntas.
- Cuando no reciben un archivo como argumento, los comandos de texto leen de la entrada estándar.
- Ctrl+D indica el fin de la entrada: el programa termina su trabajo y sale normalmente. Ctrl+C lo interrumpe.
- Un comando que parece colgado suele estar esperando datos del teclado.
- Un filtro lee su entrada, la transforma y escribe en su salida. Los comandos como
ls,cpormno leen su entrada. - La shell conecta los canales antes de ejecutar el comando, que no recibe los operadores ni sabe que hubo una redirección.
- Un comando se comunica por cuatro vías: argumentos, entrada, salidas y código de salida.
16. Preguntas de repaso
Intenta responder cada una antes de abrir la respuesta.
1. ¿Cuáles son los tres canales estándar y qué número tiene cada uno?
La entrada estándar, 0; la salida estándar, 1; y el error estándar, 2.
2. ¿A qué están conectados por defecto?
Los tres a la terminal: la entrada recibe lo que se escribe en el teclado, y las dos salidas aparecen en la pantalla.
3. ¿Qué es un descriptor de archivo?
Un número con el que un proceso se refiere a un archivo, o a otro objeto de lectura o escritura, que tiene abierto.
4. ¿Qué significa el 2 en 2>/dev/null?
Es el descriptor del error estándar. La expresión envía ese canal al sumidero, con lo que los mensajes de error se descartan.
5. En la pantalla, la salida y los errores se ven juntos. ¿Cómo se comprueba que son canales distintos?
Redirigiendo uno por vez. Con > /dev/null desaparecen los resultados y quedan los errores; con 2> /dev/null, al revés.
6. ¿Por qué los mensajes de error no viajan por la salida estándar?
Porque se mezclarían con los resultados y serían procesados como datos por el comando siguiente, o quedarían dentro de un archivo, sin que la persona que opera los viera.
7. Además de los errores, ¿qué otras cosas se escriben en el canal 2?
Los avisos, los indicadores de progreso, las preguntas al usuario y el mensaje de uso cuando el comando se invocó mal.
8. ¿De dónde lee sort si se lo ejecuta sin argumentos?
De la entrada estándar, que por defecto es el teclado. Espera líneas hasta recibir el fin de entrada.
9. ¿Qué diferencia hay entre Ctrl+D y Ctrl+C?
Ctrl+D indica que no hay más datos: el programa procesa lo recibido y termina normalmente. Ctrl+C lo interrumpe, y el resultado se pierde.
10. ¿Por qué Ctrl+D cierra la shell?
Porque la shell lee los comandos de su entrada estándar. Al recibir el fin de archivo, entiende que no habrá más comandos y termina.
11. Escribiste grep error y pulsaste Enter. No aparece nada. ¿Qué ocurre?
Falta el nombre del archivo, y grep está leyendo de la entrada estándar: espera que escribas. Se sale con Ctrl+C.
12. ¿Qué es un filtro? Da tres ejemplos.
Un programa que lee texto de su entrada estándar, lo transforma y escribe el resultado en su salida estándar. Por ejemplo, sort, grep y wc.
13. ¿Por qué echo archivo.txt | rm no borra el archivo?
Porque rm no lee su entrada estándar: recibe los nombres como argumentos.
14. ¿Por qué wc -l < notas.txt no muestra el nombre del archivo?
Porque el archivo lo abre la shell y lo conecta a la entrada del comando. wc no recibe ningún nombre: solo datos.
15. ¿Cuáles son las cuatro vías por las que un comando se comunica con el exterior?
Los argumentos y la entrada estándar, por las que recibe; las salidas estándar y de error, y el código de salida, por las que entrega.
Para practicar
- Ejecuta
ttyy luegols -l /proc/self/fd. Abre otra terminal y repite. ¿Qué cambia? - Ejecuta
ls -l /proc/self/fd > /tmp/fd.txty mira el archivo concat. ¿A qué apuntaba el descriptor 1 durante ese comando? - Repite la demostración de la sección 5 con
cat notas.txt nada.txt: descarta cada canal por separado, y luego los dos, y mira el código de salida. - Ejecuta
find /etc -name "*.conf" | wc -l. ¿Los mensajes de permiso denegado fueron contados? ¿Por qué aparecieron en la pantalla? - Ejecuta
catsin argumentos, escribe tres líneas y termina con Ctrl+D. Repite terminando con Ctrl+C, y compara los códigos de salida conecho $?. - Ejecuta
wcsin argumentos, escribe un párrafo y pulsa Ctrl+D. Repite consort -ry conhead -n 2. ¿En qué momento escribe cada uno su resultado? - Clasifica estos comandos como fuente, filtro o ninguno:
date,tail,mkdir,whoami,tr,pwd,uniq,touch. - Compara
wc -c informe.txt,wc -c < informe.txtycat informe.txt | wc -c. ¿En cuáles conocewcel nombre del archivo? - Ejecuta
ls --color=autoyls --color=auto | cat. Explica la diferencia con lo dicho en la sección 13. - Prueba
ls --help | head -n 3yls --opcion-falsa | head -n 3. ¿En cuál actuóhead, y qué dice eso sobre el canal por el que viajó cada texto?