← Automatización con Scripts en Bash Bloque 2 · Variables y datos · Tema 7 de 42

Tema 7

Aritmética en Bash

Contar archivos copiados, calcular un porcentaje de uso, medir cuánto tardó una tarea, decidir si un valor supera un umbral: casi todo script hace cuentas. Bash calcula con números enteros, rápido y sin salir de la shell, pero con reglas que sorprenden: la división descarta los decimales, un cero a la izquierda cambia la base y un incremento puede detener el script. Este tema explica esas reglas y qué hacer cuando hacen falta decimales.

1. Todo es texto, hasta que se calcula

Como vimos en el tema 5, una variable de Bash guarda siempre texto. Escribir una operación no la resuelve: 2+3 es una cadena de tres caracteres, y += une textos.

terminal
$ echo 2+3
2+3
$ n=5; n+=1; echo "$n"
51

Para que Bash trate un texto como número hay que pedírselo explícitamente, con un contexto aritmético. Dentro de él, los textos se interpretan como números enteros, los nombres como variables, y los símbolos como operadores. Hay dos formas de abrir ese contexto, y las dos usan doble paréntesis:

FormaQué esProduceSe usa para
$(( expresión ))Una expansión, como $var o $( ).El resultado, como texto.Usar el resultado: asignarlo, mostrarlo, pasarlo a un comando.
(( expresión ))Un comando.Un código de salida: 0 si el resultado no es cero.Modificar variables y tomar decisiones con if y while.

2. La expansión aritmética: $(( ))

$(( expresión )) calcula la expresión y se reemplaza por el resultado. Dentro de los paréntesis las variables se escriben sin $ (aunque con $ también funcionan), y los espacios son libres, a diferencia de una asignación:

terminal
$ copiados=12; omitidos=3
$ total=$(( copiados + omitidos ))
$ echo "$total"
15
$ echo "Minutos en una semana: $(( 60 * 24 * 7 ))"
Minutos en una semana: 10080
$ sleep $(( RANDOM % 30 ))                # esperar entre 0 y 29 segundos

Los operadores son los de la mayoría de los lenguajes de programación, con la precedencia habitual: primero la potencia, luego la multiplicación, la división y el resto, y por último la suma y la resta. Los paréntesis cambian el orden.

OperadorOperaciónEjemploResultado
+ -Suma y resta$(( 10 - 4 ))6
*Multiplicación$(( 6 * 7 ))42
/División entera$(( 7 / 2 ))3
%Resto de la división$(( 7 % 2 ))1
**Potencia$(( 2 ** 10 ))1024
( )Agrupar$(( (2 + 3) * 4 ))20

Dentro de $(( )) el * no se expande como comodín ni hace falta escaparlo, porque el contexto aritmético se analiza aparte. Es una de las ventajas frente al antiguo expr, como veremos en la sección 7.

3. División entera, resto y redondeo

La aritmética de Bash es entera: la división descarta la parte decimal, sin redondear. Con números negativos, descarta hacia el cero, y el resto toma el signo del dividendo:

terminal
$ echo $(( 7 / 2 )) $(( 7 % 2 ))
3 1
$ echo $(( -7 / 2 )) $(( -7 % 2 ))
-3 -1
$ echo $(( 5 / 0 ))
bash: 5 / 0 : division by 0 (error token is "0 ")

La división por cero es un error que interrumpe la línea en que ocurre. En un script, cuando el divisor viene de los datos, como el total de líneas de un archivo que podría estar vacío, conviene comprobarlo antes.

Que la división sea entera obliga a pensar el orden de las operaciones. El caso típico es el porcentaje: si se divide primero, el resultado intermedio se trunca a cero.

terminal · ¿qué porcentaje son 45 de 60?
$ echo $(( 45 / 60 * 100 ))                # 45/60 da 0, y 0 × 100 = 0
0
$ echo $(( 45 * 100 / 60 ))                # multiplicar primero
75

La regla es multiplicar antes de dividir. Y para redondear en lugar de truncar, se suma la mitad del divisor antes de dividir: (a + b / 2) / b. Por ejemplo, 2 de 3 es un 66,67 %:

terminal
$ echo $(( 2 * 100 / 3 ))                  # truncado
66
$ echo $(( (2 * 100 + 3 / 2) / 3 ))        # redondeado
67

El resto, por su parte, es más útil de lo que parece. Sirve para saber si un número es par (n % 2 da 0), para hacer algo cada tantas vueltas de un bucle (i % 100 == 0), para descomponer cantidades en unidades, como segundos en horas y minutos (sección 14), y para obtener un número al azar dentro de un rango: RANDOM % 6 + 1 simula un dado.

4. El comando (( ))

Sin el $ delante, (( expresión )) es un comando: calcula la expresión y no produce texto. Sirve para dos cosas. La primera, modificar variables con los operadores de asignación, sin repetir el nombre:

terminal
$ (( total = 10 ))
$ (( total += 5 ))                         # total = total + 5
$ (( total *= 2 ))                         # total = total * 2
$ echo "$total"
30
FormaEquivale a
(( x += n )), (( x -= n ))x=$(( x + n )), x=$(( x - n ))
(( x *= n )), (( x /= n )), (( x %= n ))Lo mismo con multiplicación, división y resto.
(( x++ )), (( x-- ))Sumar o restar 1, después de usar el valor.
(( ++x )), (( --x ))Sumar o restar 1, antes de usar el valor.

La segunda, y la más importante, es tomar decisiones. Como todo comando, (( )) termina con un código de salida, y la regla es: si el resultado de la expresión es distinto de cero, el código es 0, es decir, éxito o «verdadero»; si el resultado es cero, el código es 1, «falso».

terminal
$ (( 5 > 3 )); echo $?
0
$ (( 0 )); echo $?
1
$ uso=93
$ (( uso >= 90 )) && echo "Disco casi lleno"
Disco casi lleno

La regla parece invertida respecto de otros lenguajes, donde 0 es falso, pero es coherente: en la expresión, 0 es falso; en el código de salida, 0 es éxito. (( )) hace la traducción. Lo retomaremos en el tema 10, porque es la base de cómo deciden if y while.

5. Incrementar, y la trampa del cero

Contar es lo más común que hace un script con números, y hay varias formas de sumar uno a un contador. Todas dejan el mismo valor en la variable, pero no el mismo código de salida:

terminal
$ n=0; (( n++ )); echo "código $?, n vale $n"
código 1, n vale 1
$ n=0; (( ++n )); echo "código $?, n vale $n"
código 0, n vale 1

n++ incrementa la variable, pero el valor de la expresión es el que tenía antes: cero. Y una expresión que vale cero da código de salida 1. En la terminal no importa. En un script con set -e, que se detiene ante cualquier comando que falle, es una trampa clásica: el primer (( contador++ )) con el contador en cero termina el script en silencio, sin ningún mensaje.

Contar de forma segura

En scripts con set -e, usa contador=$(( contador + 1 )) o (( ++contador )). La primera es una asignación, que siempre termina con éxito; la segunda vale el número ya incrementado, que nunca es cero si se parte de cero. Es la forma que usaron los scripts de los temas 1 y 4. Evita (( contador++ )) y (( contador += 0 )) como instrucciones sueltas.

6. Comparaciones y decisiones

Dentro del contexto aritmético se puede comparar con los operadores habituales, que dan 1 si la comparación es cierta y 0 si no. Combinadas con (( )), sirven directamente como condiciones:

OperadorSignificadoOperadorSignificado
==Igual!=Distinto
<Menor>Mayor
<=Menor o igual>=Mayor o igual
&&Y lógico||O lógico
!Negaciónc ? a : ba si c es cierto; si no, b
condiciones aritméticas
if (( uso >= UMBRAL )); then
  echo "Disco casi lleno: $uso %"
fi

(( errores == 0 && avisos < 10 )) && echo "Todo en orden"

while (( intentos < 5 )); do       # reintentar hasta cinco veces (tema 15)
  …
done

Dentro de (( )), los símbolos < y > son comparaciones, no redirecciones, porque Bash analiza el interior como una expresión. Fuera, en [ ] o [[ ]], no es así: allí los números se comparan con -lt, -gt y sus parientes, y < compara textos alfabéticamente. Para comparar números, (( )) es la forma más legible, y la que usará este curso.

El operador ternario, ?:, elige entre dos valores numéricos según una condición, en una sola expresión:

terminal
$ intentos=3
$ espera=$(( intentos > 2 ? 60 : 5 ))     # esperar más tras varios fallos
$ echo "$espera"
60

7. let, expr y declare -i

En scripts antiguos encontrarás otras formas de calcular. Conviene reconocerlas, aunque no usarlas:

Forma antiguaQué esPor qué no usarla
let "n = n + 1"Un comando interno, equivalente a (( )).Necesita comillas para los espacios y los *; (( )) hace lo mismo sin ellas.
n=`expr $n + 1`Un programa externo, de la época anterior a la aritmética de la shell.Crea un proceso por operación; el * hay que escaparlo (expr 5 \* 2), y cada operador debe ir separado por espacios.
declare -i n; n=n+1Una variable con atributo entero: toda asignación se calcula.El cálculo ocurre sin que nada en la línea lo indique, y += cambia de significado, como vimos en el tema 5.

La regla del curso es simple: $(( )) cuando se necesita el resultado, y (( )) para modificar variables y para condiciones.

8. Los límites de los enteros

Bash calcula con enteros de 64 bits con signo. El mayor número representable es 9 223 372 036 854 775 807, algo más de nueve trillones, y el menor, su negativo menos uno. Es suficiente para casi todo, incluidos tamaños de archivo en bytes y marcas de tiempo en milisegundos. Pero si un cálculo se pasa de ese límite, el resultado da la vuelta sin ningún aviso:

terminal
$ echo $(( 2**63 - 1 ))
9223372036854775807
$ echo $(( 9223372036854775807 + 1 ))     # desbordamiento: pasa al extremo negativo
-9223372036854775808
$ echo $(( 2**64 ))
0

En la práctica, el riesgo aparece al multiplicar para preservar decimales, como en la sección 3. Un tamaño de 10 terabytes en bytes, multiplicado por 1000, todavía cabe; multiplicado por un millón, ya no. Si un cálculo maneja números muy grandes, conviene pensar el orden de las operaciones o pasar a bc, que no tiene límite de tamaño.

9. Ceros a la izquierda y bases

En el contexto aritmético, un número que empieza con 0 se interpreta en octal, base 8, y uno que empieza con 0x, en hexadecimal. Es una herencia del lenguaje C, y es la causa de uno de los errores más desconcertantes de Bash:

terminal
$ echo $(( 07 + 1 ))
8
$ echo $(( 010 + 1 ))                     # 010 en octal es 8
9
$ echo $(( 08 + 1 ))                      # 8 no es un dígito octal
bash: 08: value too great for base (error token is "08")

El problema real aparece con fechas y horas, que date y otros programas escriben con ceros a la izquierda. Un script que calcula con el mes o la hora funciona perfectamente de enero a julio, y falla en agosto y septiembre, o a las 8 y a las 9 de la mañana:

un error que solo aparece algunas horas del día
hora="$(date +%H)"                  # "08" a las ocho de la mañana
siguiente=$(( hora + 1 ))           # error: 08 no es octal válido

La solución es indicar la base explícitamente con el prefijo 10#, que obliga a leer el número en decimal. Funciona también con variables: $(( 10#$hora + 1 )). Otra alternativa es pedirle a date el número sin ceros: date +%-H en GNU.

El mismo prefijo sirve para cualquier base entre 2 y 64, lo que permite convertir números entre sistemas. Para la conversión inversa, de decimal a otra base, printf tiene formatos para octal y hexadecimal:

terminal
$ echo $(( 10#08 )) $(( 16#ff )) $(( 0x1f )) $(( 2#1010 ))
8 255 31 10
$ printf '%o %x %X\n' 493 255 255         # octal, hexadecimal
755 ff FF

El octal tiene un uso cotidiano en Linux: los permisos. 755 es un número octal, y printf '%o' 493 muestra que 493 en decimal es exactamente ese permiso.

10. Validar antes de calcular

El contexto aritmético es muy tolerante, y eso es peligroso cuando los datos vienen de afuera. Un texto que no es un número no siempre produce un error: si es una palabra, Bash la toma como nombre de variable; si esa variable no existe, vale cero.

terminal
$ x=abc; echo $(( x + 1 ))                 # «abc» es una variable inexistente: vale 0
1
$ x="3 + 4"; echo $(( x * 2 ))             # el valor se evalúa como expresión
14
$ x=12abc; echo $(( x + 1 ))
bash: 12abc: value too great for base (error token is "12abc")

Los dos primeros casos fallan en silencio, con un resultado incorrecto. Y hay un problema más grave: como el valor se evalúa como expresión, un texto especialmente preparado puede hacer que Bash ejecute comandos al calcularlo. Por eso, todo número que llega como argumento, desde un archivo o desde el teclado debe validarse antes de usarse en un cálculo. La forma más clara es con una expresión regular, que veremos en el tema 28; por ahora, basta con la receta:

aceptar solo enteros no negativos
dias="${1:-30}"
if [[ ! "$dias" =~ ^[0-9]+$ ]]; then
  echo "Error: los días deben ser un número entero, no «$dias»" >&2
  exit 2
fi
dias=$(( 10#$dias ))                # quitar ceros a la izquierda: 007 → 7

La última línea completa la validación: un número como 007 pasa la expresión regular, pero se leería en octal. Con 10#, se normaliza a decimal una sola vez, y el resto del script ya puede usarlo sin precauciones.

11. Evitar los decimales

Antes de recurrir a otra herramienta para calcular con decimales, conviene preguntarse si hacen falta. Muchas veces se pueden evitar eligiendo una unidad más pequeña, en la que todas las cantidades son enteras: centavos en lugar de pesos, milisegundos en lugar de segundos, bytes en lugar de megabytes. Se calcula con enteros, y solo al mostrar el resultado se lo divide para presentarlo:

terminal · precios en centavos
$ precio=12550; cantidad=3                 # $125,50
$ total=$(( precio * cantidad ))
$ printf 'Total: $%d,%02d\n' $(( total / 100 )) $(( total % 100 ))
Total: $376,50

La división entera da la parte entera, el resto da los centavos, y %02d los completa con un cero a la izquierda cuando son menos de diez. El mismo truco sirve para mostrar un porcentaje con un decimal: se calcula «por mil» en lugar de «por cien», y se separan las unidades de las décimas.

terminal · 2 de 3, con un decimal
$ por_mil=$(( (2 * 1000 + 3 / 2) / 3 ))     # 667, redondeado
$ printf '%d,%d %%\n' $(( por_mil / 10 )) $(( por_mil % 10 ))
66,7 %

12. Decimales con bc

Cuando los decimales son inevitables, como en un promedio, una tasa o una conversión de unidades, Bash recurre a un programa externo. El clásico es bc, una calculadora de precisión arbitraria que lee expresiones desde su entrada. No siempre viene instalado; en Debian y Ubuntu, sudo apt install bc.

terminal
$ echo "10 / 3" | bc                       # por defecto, sin decimales
3
$ echo "scale=2; 10 / 3" | bc              # scale: cantidad de decimales
3.33
$ echo "10 / 3" | bc -l                    # -l: biblioteca matemática, 20 decimales
3.33333333333333333333
$ promedio=$(echo "scale=2; 1873 / 26" | bc)
$ echo "$promedio"
72.03

scale indica cuántos decimales conservar, y bc trunca, no redondea. Para comparar números con decimales, que (( )) no admite, se le pide a bc la comparación: responde 1 si es cierta y 0 si no, y ese resultado sí se puede usar en (( )).

comparar decimales
carga="$(cut -d' ' -f1 /proc/loadavg)"      # por ejemplo, 2.37
if (( $(echo "$carga > 2.0" | bc) )); then
  echo "Carga alta: $carga"
fi

13. Decimales con awk

awk, que conociste en el curso de Terminal, calcula con decimales de forma nativa y está instalado en todos los sistemas. Para un cálculo suelto, se usa con un bloque BEGIN, que se ejecuta sin leer ninguna entrada, y los valores se pasan con -v:

terminal
$ awk -v a=1873 -v b=26 'BEGIN { printf "%.2f\n", a / b }'
72.04

A diferencia de bc, el printf de awk redondea: 72,038… se muestra como 72.04. Pero el gran terreno de awk no son los cálculos sueltos, sino los que recorren un archivo. Sumar o promediar una columna, que en Bash requeriría un bucle, en awk es una línea:

terminal · tiempos de respuesta en milisegundos, uno por línea
$ awk '{ suma += $1; n++ } END { printf "%d mediciones, promedio %.1f ms\n", n, suma / n }' tiempos.txt
26 mediciones, promedio 72.0 ms
NecesitasUsa
Contar, sumar enteros, comparar, porcentajes aproximados$(( )) y (( )): sin procesos, lo más rápido.
Un resultado con decimales para mostrarEnteros en una unidad menor, o awk con printf.
Comparar números con decimalesbc o awk.
Precisión arbitraria o números enormesbc.
Cálculos sobre las columnas de un archivoawk, siempre.
printf, decimales y configuración regional

El printf de Bash también da formato a decimales (printf '%.2f' 3.14159), pero respeta la configuración regional, y en español el separador decimal es la coma. Con un idioma como es_AR.UTF-8, printf '%.2f\n' 3.14159 responde invalid number y muestra 3,00, porque espera 3,14159. Como bc y awk producen siempre el punto, conviene dar formato dentro de awk, o ejecutar printf con LC_NUMERIC=C.

14. Calcular con fechas y tiempos

Las fechas no son números, pero se convierten en uno: la cantidad de segundos transcurridos desde el 1 de enero de 1970, llamada tiempo Unix o epoch. date +%s da ese número para el momento actual, y date -d para cualquier fecha. A partir de ahí, las diferencias entre fechas son restas:

terminal
$ date +%s
1792000000
$ ahora=$(date +%s); fin=$(date -d 2026-12-31 +%s)
$ echo "Faltan $(( (fin - ahora) / 86400 )) días para fin de año"
Faltan 77 días para fin de año

86 400 son los segundos de un día. Para medir cuánto tarda una tarea dentro de un script, la variable SECONDS del tema 5 es la más simple. Y para presentar una duración en horas, minutos y segundos, se combinan la división y el resto:

mostrar una duración
inicio=$SECONDS
tar -czf respaldo.tgz ~/proyecto
duracion=$(( SECONDS - inicio ))           # por ejemplo, 3725 segundos

printf 'Duración: %02d:%02d:%02d\n' \
  $(( duracion / 3600 )) $(( duracion % 3600 / 60 )) $(( duracion % 60 ))
# Duración: 01:02:05

duracion / 3600 da las horas completas; duracion % 3600 los segundos que sobran de ellas, y dividido por 60, los minutos; duracion % 60, los segundos restantes. Es la misma descomposición que se usa para pasar bytes a kilobytes y megabytes, o centavos a pesos.

15. Un script completo

Este script muestra cuánto ocupa un directorio y qué porcentaje del disco representa, con un decimal y sin salir de la aritmética entera. Reúne la multiplicación antes de la división, el redondeo y la presentación con printf:

ocupacion
#!/usr/bin/env bash
#
# ocupacion — cuánto ocupa un directorio y qué parte del disco representa.
#
# Uso: ocupacion [DIRECTORIO]
#
set -euo pipefail
export LC_ALL=C                          # salida de du y df sin variaciones regionales

dir="${1:-.}"

bytes=$(du -sb -- "$dir" | cut -f1)               # tamaño del directorio
total=$(df -B1 --output=size -- "$dir" | tail -1)  # tamaño del disco

# Megabytes, redondeados: se suma medio MiB antes de dividir.
mib=$(( (bytes + 524288) / 1048576 ))

# Porcentaje con un decimal: se calcula por mil y se separa la última cifra.
por_mil=$(( (bytes * 1000 + total / 2) / total ))

printf '%s ocupa %d MiB: el %d.%d %% del disco\n' \
  "$dir" "$mib" $(( por_mil / 10 )) $(( por_mil % 10 ))
terminal
$ ocupacion ~/videos
/home/ana/videos ocupa 1229 MiB: el 3.0 % del disco
$ ocupacion ~/proyecto
/home/ana/proyecto ocupa 48 MiB: el 0.1 % del disco

16. Errores frecuentes

EscribisteQué pasaCorrección
n+=1Une texto: 5 pasa a 51.(( n += 1 )) o n=$(( n + 1 ))
(( n++ )) con set -eSi n era 0, el script termina en silencio.n=$(( n + 1 )) o (( ++n ))
$(( a / b * 100 ))Si a < b, da 0.$(( a * 100 / b ))
$(( hora + 1 )) con hora=08value too great for base$(( 10#$hora + 1 ))
$(( 1.5 * 2 ))syntax error: invalid arithmetic operatorbc, awk, o enteros en otra unidad.
$(( total / cantidad )) con cantidad 0division by 0Comprobar antes: (( cantidad > 0 )).
$(( x + 1 )) con x sin validarResultados silenciosamente incorrectos, o ejecución de código.Validar con =~ ^[0-9]+$.
[ $a > $b ]Crea un archivo llamado como $b: > es una redirección.(( a > b ))
printf '%.2f' "$x" en españolinvalid number si x usa punto decimal.LC_NUMERIC=C printf …, o awk.

17. Resumen

18. Preguntas de repaso

Intenta responder cada una antes de abrir la respuesta.

1. ¿Qué diferencia hay entre $(( a + b )) y (( a + b ))?

La primera es una expansión: se reemplaza por el resultado, que se puede asignar o mostrar. La segunda es un comando: no produce texto, y termina con código 0 si el resultado es distinto de cero y con 1 si es cero.

2. ¿Cuánto valen $(( 17 / 5 )) y $(( 17 % 5 ))?

3 y 2. La división es entera y descarta los decimales; el resto es lo que sobra: 17 = 3 × 5 + 2.

3. ¿Por qué $(( 30 / 40 * 100 )) da 0, y cómo se corrige?

Porque 30 / 40 es 0 en división entera, y 0 × 100 es 0. Se corrige multiplicando primero: $(( 30 * 100 / 40 )), que da 75.

4. ¿Cómo se calcula a / b redondeado en lugar de truncado?

Sumando la mitad del divisor antes de dividir: $(( (a + b / 2) / b )).

5. ¿Por qué (( n++ )) puede detener un script con set -e?

Porque el valor de n++ es el que n tenía antes de incrementarse. Si era 0, la expresión vale 0, y (( )) termina con código 1, que set -e trata como un fallo.

6. ¿Qué código de salida da (( 3 > 5 ))?

1, porque la comparación es falsa y vale 0, y una expresión que vale 0 da código de salida 1.

7. ¿Qué hace pausa=$(( fallos > 3 ? 300 : 10 ))?

Asigna 300 a pausa si fallos es mayor que 3, y 10 en caso contrario.

8. ¿Por qué no conviene usar expr en scripts nuevos?

Porque es un programa externo, que crea un proceso por operación, y exige escapar el * y separar cada operador con espacios. $(( )) hace lo mismo dentro de Bash, con una sintaxis más natural.

9. ¿Qué ocurre si un cálculo supera 9 223 372 036 854 775 807?

Se desborda: el resultado da la vuelta hacia los números negativos, sin ningún mensaje de error.

10. Un script falla con value too great for base solo a las 8 y a las 9 de la mañana. ¿Por qué?

Porque calcula con la hora que da date +%H, que a esas horas es 08 o 09. El cero inicial hace que Bash lo lea como octal, donde 8 y 9 no son dígitos válidos. Se corrige con 10#$hora.

11. Con x=hola, ¿qué da $(( x + 1 )), y por qué es un problema?

Da 1, porque hola se interpreta como el nombre de una variable, que no existe y vale 0. El problema es que no hay ningún error: el resultado es incorrecto en silencio. Por eso los números que vienen de afuera deben validarse.

12. ¿Cómo se muestra un total de 12 345 centavos como $123,45 sin usar decimales?

Con printf '$%d,%02d\n' $(( t / 100 )) $(( t % 100 )): la división da los pesos, el resto los centavos, y %02d agrega un cero si son menos de diez.

13. ¿Qué muestra echo "scale=3; 2 / 3" | bc?

.666. scale fija tres decimales, y bc trunca en lugar de redondear. (bc omite el cero antes del punto.)

14. ¿Por qué printf '%.2f\n' 3.14159 puede fallar en un sistema en español?

Porque printf respeta la configuración regional, y en español el separador decimal es la coma. Espera 3,14159, y con un punto responde invalid number. Se evita con LC_NUMERIC=C o dando formato con awk.

15. ¿Cómo se calcula la cantidad de días entre hoy y una fecha?

Convirtiendo las dos fechas a segundos con date +%s y date -d FECHA +%s, restándolas y dividiendo por 86 400, la cantidad de segundos de un día.

Para practicar

  1. Calcula con $(( )) cuántos segundos tiene un año de 365 días, y cuántos días son mil millones de segundos.
  2. Escribe un script que reciba dos números y muestre su suma, su producto, el cociente entero, el resto y el porcentaje que el primero representa del segundo, redondeado. Valida que los dos sean enteros.
  3. Comprueba en tu terminal la diferencia de código de salida entre (( n++ )) y (( ++n )) partiendo de n=0. Luego escribe un script con set -e que cuente con (( n++ )) y observa qué pasa.
  4. Prueba h=09; echo $(( h + 1 )) y corrígelo con 10#.
  5. Muestra el porcentaje de 7 sobre 9 con dos decimales, de tres formas: con enteros «por diez mil», con bc y con awk.
  6. Crea un archivo con diez números, uno por línea, y calcula con awk su suma, su promedio y el mayor.
  7. Agrega al script ocupacion la cantidad de archivos del directorio, contada con find "$dir" -type f | wc -l, y el tamaño medio por archivo en KiB.
  8. Escribe una línea que muestre cuántos días faltan para tu próximo cumpleaños.