1. Sin archivos intermedios
Con las redirecciones del tema 23 ya se puede hacer que el resultado de un comando sea procesado por otro. Para contar cuántas cosas hay en un directorio:
$ cd ~/practica
$ ls > /tmp/lista.txt # la salida de ls, a un archivo
$ wc -l < /tmp/lista.txt # el archivo, a la entrada de wc
4
$ rm /tmp/lista.txt
Funciona, y es incómodo: tres líneas, un nombre que inventar y un archivo que limpiar, para algo que no interesa conservar. El archivo solo sirvió de puente entre la salida de uno y la entrada del otro. La tubería es ese puente, sin el archivo:
$ ls | wc -l
4
2. El operador |
Una tubería, en inglés pipe, conecta la salida estándar de un comando con la entrada estándar del siguiente. Se escribe con una barra vertical, |, entre los dos.
La línea se lee como una cadena de montaje. Cada comando recibe lo que hizo el anterior, le aplica su transformación y lo entrega al siguiente:
$ sort tareas.txt | head -n 2
Comprar pan
Estudiar vim
sort ordena las cinco líneas del archivo. En lugar de aparecer en la pantalla, esas cinco líneas entran a head, que deja pasar las dos primeras. Ninguno de los dos comandos sabe que está en una tubería: sort escribe en su salida, como siempre, y head lee de su entrada, como siempre. Es el modelo del tema 22 dando su fruto.
No hay límite para la cantidad de eslabones. Los que están en el medio deben ser filtros: comandos que leen de su entrada y escriben en su salida.
3. Qué ocurre por dentro
Una tubería no ejecuta un comando, espera a que termine y luego ejecuta el otro. Ese sería el método del archivo intermedio. Hace algo más eficiente, y saberlo explica varios comportamientos:
| Hecho | Consecuencia |
|---|---|
| Todos los comandos arrancan a la vez, como procesos simultáneos. | El segundo empieza a trabajar con las primeras líneas, sin esperar las últimas. |
| Los datos no pasan por el disco. El kernel los guarda en una zona de memoria pequeña, mientras esperan a ser leídos. | Se pueden procesar archivos de gigabytes sin ocupar espacio ni memoria adicionales. |
| Si quien lee es más lento, quien escribe espera. Y al revés. | Los procesos se regulan solos; no hay desbordamientos. |
| Cuando quien lee termina, quien escribe es detenido. | Una tubería se corta en cuanto se obtuvo lo necesario. |
La última fila se comprueba con un comando hecho para no terminar nunca. yes escribe la letra y, línea tras línea, indefinidamente:
$ yes | head -n 3
y
y
y
$
El indicador volvió enseguida. head leyó tres líneas y terminó; al quedarse sin nadie que leyera, yes fue interrumpido por el sistema. Por eso | head al final de un comando que produce millones de líneas no tarda lo que tardaría el comando completo.
Hay una excepción natural a ese flujo continuo: los comandos que necesitan todos los datos antes de poder responder, como sort, que no puede saber cuál es la primera línea hasta haber visto la última. Esos retienen todo y escriben al final.
4. Construir una tubería paso a paso
Las tuberías largas no se escriben de un tirón. Se construyen de a un eslabón, mirando el resultado de cada paso antes de agregar el siguiente. Veámoslo con una pregunta concreta: ¿qué shells usan las cuentas de este sistema, y cuántas cuentas hay de cada una?
Los datos están en /etc/passwd, cuyo séptimo campo es la shell, como vimos en el tema 16. Usaremos tres filtros que estudiamos a fondo en el tema 26; por ahora alcanza con una línea sobre cada uno:
| Filtro | Qué hace |
|---|---|
cut -d: -f7 | De cada línea, deja solo el séptimo campo, tomando los dos puntos como separador. |
sort | Ordena las líneas. Con -n, por valor numérico; con -r, al revés. |
uniq -c | Funde las líneas iguales que están juntas, y antepone cuántas eran. |
$ cut -d: -f7 /etc/passwd | head -n 4
/bin/bash
/usr/sbin/nologin
/usr/sbin/nologin
/usr/sbin/nologin
$ cut -d: -f7 /etc/passwd | sort | head -n 4
/bin/bash
/bin/bash
/bin/false
/bin/false
$ cut -d: -f7 /etc/passwd | sort | uniq -c
2 /bin/bash
5 /bin/false
1 /bin/sync
38 /usr/sbin/nologin
$ cut -d: -f7 /etc/passwd | sort | uniq -c | sort -rn
38 /usr/sbin/nologin
5 /bin/false
2 /bin/bash
1 /bin/sync
Cuatro comandos, ninguno de los cuales sabe nada de usuarios ni de shells, respondieron la pregunta: de las 46 cuentas, solo dos pueden iniciar sesión, root y ana. No existe un programa llamado «contar shells»; no hizo falta.
El método tiene tres reglas. En cada paso se recupera la línea anterior con la flecha arriba y se le agrega un eslabón. Mientras se construye, un | head provisorio al final evita que la pantalla se llene. Y si un paso no da lo esperado, el error está en el último eslabón agregado, porque los anteriores ya fueron vistos funcionando.
5. La filosofía de las herramientas pequeñas
La tubería no es solo un operador. Es la razón por la que los comandos de Unix son como son. Sus creadores, en los Laboratorios Bell, formularon en los años setenta unas pocas reglas de diseño, que se conocen como la filosofía Unix:
| Principio | En la práctica |
|---|---|
| Que cada programa haga una sola cosa, y la haga bien. | sort ordena. No cuenta, no filtra, no da formato. |
| Que los programas puedan trabajar juntos. | La salida de cualquiera debe poder ser la entrada de otro, aunque nadie haya previsto esa combinación. |
| Que se comuniquen con texto, porque es la interfaz universal. | Líneas de texto simples, sin encabezados ni adornos que estorben al que sigue. |
Esto explica rasgos de los comandos que al principio parecían rudeza. Que ls, sin opciones, no muestre un título ni un total. Que wc -l escriba un número a secas. Que nada informe «operación completada». Cada línea de más sería un estorbo para el comando siguiente, que tendría que distinguir los datos de los comentarios. El silencio y la sobriedad de la terminal son requisitos de la composición.
La ganancia es de escala. Con veinte herramientas que hacen una cosa cada una, las combinaciones posibles son miles, y cubren problemas que nadie previó. Un programa grande con veinte funciones resuelve veinte problemas.
La idea ha sido muy imitada, y hoy se la encuentra bajo otros nombres en el diseño de software en general. Su expresión más pura sigue siendo una línea con cuatro comandos y tres barras.
6. Los errores no pasan por la tubería
La tubería conecta el canal 1, y solo ese. Los mensajes de error de cada comando, que viajan por el canal 2, siguen yendo a la pantalla. Es lo que mostraba el diagrama, y lo que comprobamos en el tema 22:
$ ls notas.txt nada.txt | wc -l
ls: cannot access 'nada.txt': No such file or directory
1
Casi siempre es lo que se quiere: los errores no contaminan los datos, y siguen a la vista. Cuando sí interesa que entren a la tubería —para buscar en ellos, contarlos o paginarlos— se juntan los dos canales antes de la barra, con el operador del tema anterior:
$ ls notas.txt nada.txt 2>&1 | wc -l
2
| Se escribe | Por la tubería pasa | Uso típico |
|---|---|---|
cmd1 | cmd2 | Solo la salida. | El normal. |
cmd1 2>&1 | cmd2 | La salida y los errores. | Paginar con less un comando que produce muchos errores. |
cmd1 |& cmd2 | Lo mismo; es la abreviatura de Bash. | Ídem. |
cmd1 2>/dev/null | cmd2 | Solo la salida; los errores se descartan. | Una búsqueda con find en directorios restringidos. |
La segunda fila parece contradecir la regla del orden que aprendimos, y no lo hace. La shell prepara primero la tubería, de modo que cuando se procesa 2>&1, el canal 1 ya apunta a ella.
7. Tubería o redirección
Los dos operadores envían la salida de un comando a otro lugar, y es común confundirlos al empezar. La diferencia está en qué hay a la derecha:
comando > x | comando | x | |
|---|---|---|
x es | Un archivo | Un comando |
| Los datos | Quedan guardados | Se procesan y siguen |
| Puede haber otro eslabón después | No: es el final | Sí |
Escribir ls > wc en lugar de ls | wc no da ningún error: crea en el directorio actual un archivo llamado wc, con el listado dentro. El caso grave es el mismo descuido con una ruta, y con privilegios: una redirección hacia la ruta de un programa del sistema lo reemplaza por texto. A la derecha de > va siempre un archivo.
Los dos se combinan sin problema, y es lo habitual: una tubería que termina en una redirección guarda el resultado final. La redirección de entrada, si la hay, va en el primer eslabón.
$ cut -d: -f7 /etc/passwd | sort | uniq -c | sort -rn > /tmp/shells.txt
8. tee: guardar y seguir
Una redirección termina la tubería: lo que va al archivo ya no continúa. A veces se quieren las dos cosas, guardar una copia y seguir procesando, o guardar y ver en la pantalla. Para eso existe tee:
tee copia su entrada en dos lugares a la vez: en su salida estándar, y en el archivo que se le indica.
El nombre viene de las piezas de plomería con forma de T, que dividen un caño en dos.
$ sort tareas.txt | tee /tmp/ordenadas.txt | head -n 2
Comprar pan
Estudiar vim
$ wc -l /tmp/ordenadas.txt
5 /tmp/ordenadas.txt
Por la tubería siguieron las cinco líneas, de las que head mostró dos; y en el archivo quedaron las cinco. tee se intercaló sin alterar lo que pasaba.
| Uso | Comando |
|---|---|
| Ver la salida y guardarla a la vez | comando | tee resultado.txt |
| Lo mismo, añadiendo al archivo | comando | tee -a registro.txt |
| Incluir también los errores | comando 2>&1 | tee registro.txt |
| Guardar un paso intermedio de una tubería | cmd1 | tee paso.txt | cmd2 |
| Escribir en un archivo que requiere privilegios | comando | sudo tee /etc/archivo |
El primer uso es el de todos los días: una instalación o una compilación larga, que se quiere seguir en la pantalla y además conservar para revisar si algo falla. Con > no se vería nada mientras ocurre.
El último lo adelantamos en el tema 19, y ahora se entiende del todo. Con sudo comando > /etc/archivo, el archivo lo abre la shell, sin privilegios. Con | sudo tee, lo abre tee, que corre como root. Como tee además repite todo en la pantalla, suele añadirse > /dev/null al final para silenciarlo.
9. xargs: de líneas a argumentos
En el tema 22 vimos que no todos los comandos son filtros. ls, cp, rm, mkdir o chmod no leen su entrada: esperan nombres como argumentos. Ponerlos al final de una tubería no sirve, porque ignoran lo que les llega.
Sin embargo, es una necesidad constante: se tiene una lista de archivos, producida por un comando, y se quiere aplicarles otro. El adaptador entre los dos mundos es xargs:
xargs lee líneas de su entrada estándar y ejecuta un comando poniéndolas como argumentos.
$ find . -name "*.txt" | wc -l # wc lee la entrada: cuenta los nombres
3
$ find . -name "*.txt" | xargs wc -l # xargs los pasa como argumentos: cuenta el contenido
1 ./notas.txt
361 ./informe.txt
5 ./tareas.txt
367 total
La comparación muestra la diferencia entre las dos vías. En la primera línea, wc recibe por su entrada tres líneas de texto y las cuenta: son tres. En la segunda, xargs lee esas tres líneas y ejecuta wc -l ./notas.txt ./informe.txt ./tareas.txt; ahora wc recibe tres nombres de archivo, y cuenta las líneas de cada uno.
… | comando | … | xargs comando | |
|---|---|---|
| Lo que llega se usa como | Datos, por la entrada | Argumentos, en la línea de comandos |
| Sirve con | Filtros: sort, grep, wc | Comandos que actúan sobre archivos: rm, cp, chmod, ls |
Para saber qué va a ejecutar, xargs se puede usar con echo delante del comando, la lente que conocemos del tema 9; sin ningún comando, echo es de hecho lo que ejecuta por defecto.
10. xargs en detalle
| Opción | Efecto |
|---|---|
-n 1 | Ejecuta el comando una vez por cada elemento, en lugar de una sola vez con todos. |
-I {} | Reemplaza {} por cada elemento, donde aparezca. Permite ponerlo en el medio de la línea. |
-0 | Espera elementos separados por el carácter nulo, no por espacios ni saltos de línea. |
-p | Muestra cada comando y pide confirmación antes de ejecutarlo. |
-t | Muestra cada comando antes de ejecutarlo. |
-r | No ejecuta nada si la entrada está vacía. |
$ ls *.txt | xargs echo Archivos:
Archivos: informe.txt notas.txt tareas.txt
$ ls *.txt | xargs -n 1 echo Archivo:
Archivo: informe.txt
Archivo: notas.txt
Archivo: tareas.txt
$ ls *.txt | xargs -I {} echo cp {} /tmp/{}.bak
cp informe.txt /tmp/informe.txt.bak
cp notas.txt /tmp/notas.txt.bak
cp tareas.txt /tmp/tareas.txt.bak
El tercer ejemplo muestra lo que -I resuelve: sin esa opción, los elementos se agregan siempre al final, y un comando como cp, que necesita el destino después, no se podría armar. Quitando el echo, la línea haría las tres copias.
xargs tiene un punto débil, que es el de siempre: los nombres con espacios. Separa los elementos por espacios y por saltos de línea, de modo que mis notas.txt se convierte en dos argumentos. Con un comando que borra, es un accidente.
La forma segura es que los nombres viajen separados por el carácter nulo, el único que no puede formar parte de un nombre. find los escribe así con -print0, y xargs los lee así con -0: find . -name "*.tmp" -print0 | xargs -0 rm. Ningún espacio, comilla o salto de línea dentro de un nombre puede romper esa tubería. Y antes de un xargs rm, como antes de cualquier borrado, se mira la lista.
Cuando la fuente es find, hay una alternativa que vimos en el tema 10 y que no tiene este problema: -exec comando {} +. Hace lo mismo sin tubería. xargs es necesario cuando la lista viene de otro lado: un archivo, un grep, un ls.
11. El código de salida de una tubería
Cada comando de una tubería termina con su propio código de salida. La tubería entera, sin embargo, informa uno solo:
El código de salida de una tubería es el de su último comando. Los fallos de los anteriores no se reflejan en $?.
$ ls nada.txt | wc -l
ls: cannot access 'nada.txt': No such file or directory
0
$ echo $?
0
ls falló con código 2, y aun así la tubería «tuvo éxito», porque wc, el último, terminó bien. Para una persona que mira la pantalla no hay problema: el mensaje de error está ahí. Para un script, que decide qué hacer según $?, es una trampa: seguiría adelante con un resultado de cero líneas, como si fuera un dato válido.
Bash da dos remedios:
| Recurso | Qué hace |
|---|---|
"${PIPESTATUS[@]}" | La lista de los códigos de salida de todos los comandos de la última tubería, en orden. |
set -o pipefail | Hace que la tubería devuelva el código del último comando que haya fallado, y cero solo si todos tuvieron éxito. |
$ ls nada.txt 2>/dev/null | wc -l
0
$ echo "${PIPESTATUS[@]}"
2 0
$ set -o pipefail
$ ls nada.txt 2>/dev/null | wc -l
0
$ echo $?
2
$ set +o pipefail
pipefail es una de las opciones que se activan al comienzo de casi todo script serio, y la reencontrarás en el curso siguiente.
12. Los modismos de todos los días
Algunas terminaciones de tubería se repiten tanto que funcionan como palabras. Varias las venimos usando:
| Se agrega al final | Para |
|---|---|
| less | Leer con calma una salida larga. |
| head, | tail | Ver solo el comienzo, o el final. |
| wc -l | Saber cuántos resultados hay. |
| grep texto | Quedarse con las líneas que contienen algo. |
| sort | Ordenar. |
| sort | uniq | Eliminar los repetidos. |
| sort | uniq -c | sort -rn | Contar cuántas veces aparece cada valor, del más frecuente al menos. |
| tee archivo | Ver y guardar. |
| xargs comando | Aplicar un comando a cada resultado. |
La séptima fila es el modismo más valioso de toda la línea de comandos, y lo armamos pieza por pieza en la sección 4. Responde a cualquier pregunta de la forma «¿cuál es el más frecuente?»: las direcciones que más visitan un servidor, los errores que más se repiten en un registro, los comandos que más usas. Será el núcleo del proyecto del tema 42.
Ahora se puede leer entera la línea que mostramos en el tema 1 como promesa de lo que la terminal permitía:
$ du -sh * | sort -rh | head -n 5
| Eslabón | Papel | Hace |
|---|---|---|
du -sh * | Fuente | Escribe una línea por cada elemento del directorio, con el espacio que ocupa en formato legible. |
sort -rh | Filtro | Ordena esas líneas por tamaño, entendiendo los sufijos K, M y G, de mayor a menor. |
head -n 5 | Filtro | Deja pasar las cinco primeras. |
13. Errores y malos hábitos
| Se escribe | Problema | Mejor |
|---|---|---|
cat archivo | grep texto | Un proceso de más. cat solo copia el archivo a la tubería. | grep texto archivo |
sort datos.txt | uniq > datos.txt | El archivo se vacía antes de que sort lo lea: la trampa del tema 23. | Un archivo de salida distinto. |
ls | rm | rm no lee su entrada. | ls | xargs rm, o mejor un comodín. |
ls > wc | Crea un archivo llamado wc. | ls | wc |
comando | cd directorio | Cada eslabón corre en un proceso aparte: el cd no afecta a tu shell. | No se puede cambiar de directorio desde una tubería. |
ls *.txt | xargs comando | Falla con nombres que tienen espacios. | comando *.txt, o find … -exec. |
La primera fila tiene nombre propio en la cultura de Unix: el «uso inútil de cat». No es un error —el resultado es el mismo— sino un hábito de quien todavía piensa que los filtros necesitan que alguien les «pase» el archivo. Casi todos aceptan el nombre como argumento. Hay un caso en que escribirlo así es defendible: mientras se construye una tubería, tener el archivo al principio y los filtros después hace más fácil ir cambiándolos.
La quinta fila generaliza algo que vimos con sudo cd. Los comandos de una tubería se ejecutan en procesos separados de tu shell, de modo que nada de lo que hagan sobre su propio entorno —cambiar de directorio, definir una variable— persiste cuando la tubería termina.
14. Cuando una tubería no da lo esperado
Una tubería de cinco eslabones que entrega un resultado vacío no dice dónde falló. El método para averiguarlo es el mismo con el que se la construyó, recorrido al revés:
- Quitar eslabones desde el final, de a uno, hasta que la salida sea la esperada. El último que se quitó es el culpable. acortar
- Mirar la salida de ese punto con
| head: ¿tiene la forma que el siguiente filtro supone? mirar - Ver los invisibles con
| cat -A: tabulaciones donde se esperaban espacios, o al revés. mirar - Guardar un punto intermedio con
| tee /tmp/paso.txt |, para examinarlo aparte. guardar - Revisar los códigos de salida con
"${PIPESTATUS[@]}". comprobar
Las causas más frecuentes son tres. Un filtro que selecciona columnas o campos con un separador que no es el real; lo detecta el tercer paso. Un uniq sin un sort antes, que solo funde líneas iguales cuando están juntas. Y un comando del medio que no es un filtro, y deja pasar otra cosa, o nada.
La referencia del tema:
| Se escribe | Qué hace |
|---|---|
cmd1 | cmd2 | La salida de cmd1 es la entrada de cmd2. |
cmd1 2>&1 | cmd2, o cmd1 |& cmd2 | Incluye también los errores. |
cmd | tee archivo | Muestra la salida y la guarda. |
cmd | tee -a archivo | Lo mismo, añadiendo. |
cmd | xargs otro | Ejecuta otro con las líneas como argumentos. |
find … -print0 | xargs -0 otro | Lo mismo, a salvo de nombres con espacios. |
"${PIPESTATUS[@]}" | Los códigos de salida de cada eslabón. |
set -o pipefail | La tubería falla si falla cualquiera de sus comandos. |
Las tuberías conectan los datos de un comando con otro. Queda una forma más de combinar: hacer que la ejecución de un comando dependa del resultado de otro, o que su salida se convierta en parte de otra línea. Es el tema 25, que cierra el bloque.
15. Resumen
- Una tubería,
|, conecta la salida estándar de un comando con la entrada estándar del siguiente, sin archivos intermedios. - Los comandos de una tubería se ejecutan a la vez. Los datos pasan por la memoria, y cuando el que lee termina, el que escribe es detenido.
- Los eslabones intermedios deben ser filtros: comandos que leen su entrada y escriben en su salida.
- Una tubería se construye de a un paso, mirando el resultado de cada uno antes de agregar el siguiente.
- La filosofía Unix: programas que hacen una sola cosa, que pueden trabajar juntos, y que se comunican con texto.
- Por la tubería pasa solo el canal 1. Para incluir los errores se escribe
2>&1 |, o|&. - A la derecha de
>va un archivo; a la derecha de|, un comando. teecopia su entrada a un archivo y a su salida: permite ver y guardar, o guardar un paso intermedio.xargsconvierte las líneas que recibe en argumentos de un comando, para usar en una tubería comandos que no leen su entrada.- Con nombres de archivo, la combinación segura es
find -print0 | xargs -0. - El código de salida de una tubería es el de su último comando.
PIPESTATUSyset -o pipefailpermiten detectar los fallos intermedios. sort | uniq -c | sort -rncuenta las apariciones de cada valor, del más frecuente al menos.
16. Preguntas de repaso
Intenta responder cada una antes de abrir la respuesta.
1. ¿Qué conecta exactamente una tubería?
La salida estándar, el canal 1, del comando de la izquierda con la entrada estándar, el canal 0, del comando de la derecha.
2. ¿Qué ventaja tiene ls | wc -l sobre guardar el listado en un archivo y contarlo después?
No hay archivo que nombrar ni que borrar, los datos no pasan por el disco, y los dos comandos trabajan a la vez.
3. yes nunca termina, pero yes | head -n 3 sí. ¿Por qué?
Porque head termina después de leer tres líneas, y cuando el lector de una tubería termina, el sistema detiene al que escribe.
4. ¿Qué condición deben cumplir los comandos que están en el medio de una tubería?
Deben ser filtros: leer de su entrada estándar y escribir en su salida estándar.
5. Enuncia los tres principios de la filosofía Unix.
Que cada programa haga una sola cosa y la haga bien; que los programas puedan trabajar juntos; y que se comuniquen mediante texto.
6. En find / -name "*.log" | wc -l, ¿se cuentan los mensajes «Permission denied»?
No. Viajan por el canal de errores, que no pasa por la tubería: aparecen en la pantalla.
7. ¿Cómo se hace para que los errores también entren a la tubería?
Juntando los canales antes de la barra: comando 2>&1 | otro, o con la abreviatura comando |& otro.
8. ¿Qué diferencia hay entre ls > sort y ls | sort?
La primera crea un archivo llamado sort con el listado. La segunda envía el listado al comando sort.
9. ¿Qué hace tee?
Copia lo que recibe por su entrada a dos destinos: su salida estándar y un archivo.
10. ¿Por qué echo "x" | sudo tee /etc/archivo funciona y sudo echo "x" > /etc/archivo no?
En la segunda, el archivo lo abre la shell del usuario, sin privilegios. En la primera lo abre tee, que se ejecuta como root.
11. ¿Qué diferencia hay entre find . -name "*.txt" | wc -l y find . -name "*.txt" | xargs wc -l?
La primera cuenta cuántos nombres encontró find. La segunda pasa esos nombres como argumentos a wc, que cuenta las líneas de cada archivo.
12. ¿Para qué sirve la opción -I {} de xargs?
Para indicar en qué lugar de la línea se coloca cada elemento, cuando no debe ir al final; por ejemplo, como origen de un cp.
13. ¿Por qué se usa find -print0 | xargs -0?
Porque separa los nombres con el carácter nulo, que no puede aparecer en un nombre de archivo. Así, los nombres con espacios o saltos de línea no se parten en varios argumentos.
14. Un comando falla en medio de una tubería y $? vale 0. ¿Por qué, y cómo se detecta el fallo?
Porque el código de salida de una tubería es el del último comando. Se detecta con "${PIPESTATUS[@]}", o activando set -o pipefail.
15. ¿Qué hace | sort | uniq -c | sort -rn, y por qué hace falta el primer sort?
Cuenta cuántas veces aparece cada línea y las ordena de la más frecuente a la menos. El primer sort es necesario porque uniq solo funde líneas iguales que están contiguas.
Para practicar
- Averigua con una tubería cuántos programas hay en
/usr/bin, cuántas páginas hay en la sección 1 del manual y cuántos usuarios hay en el sistema. - Reconstruye paso a paso la tubería de la sección 4. Luego adáptala para contar cuántos usuarios tienen cada grupo primario: el cuarto campo de
/etc/passwd. - Muestra las tres líneas más largas de
tareas.txten orden alfabético inverso, y la línea 100 deinforme.txt, usando solosort,headytail. - Ejecuta
ls /root | wc -lyls /root 2>&1 | wc -l. Explica los dos números. - Ejecuta
ls -l /etc | tee /tmp/etc.txt | wc -ly compara conwc -l /tmp/etc.txt. - Con
findyxargs, obtén el listado largo de todos los archivos.confque están directamente en/etc, ordenados por tamaño. - Antepone
echopara ver qué haríals *.txt | xargs -I {} mv {} {}.viejo, sin ejecutarlo. - En
/tmp, crea un archivo llamadodos palabras.txt. Comparafind /tmp -name "*.txt" | xargs ls -lcon la versión que usa-print0y-0. - Ejecuta
cat nada.txt | sort | heady mira$?y"${PIPESTATUS[@]}". Repite conset -o pipefail. - Usa
historyy los filtros de la sección 4 para ver cuántos comandos distintos escribiste. Pista:history | cut -c 8-quita los números de línea.