Guiones de Bash: variables, códigos de salida y argumentos

Convierte las secuencias de comandos que escribes una y otra vez en guiones de Bash. Comienza cada guion con una línea de intérprete y haz que sea ejecutable. Almacena valores en variables, protégelos con comillas y captura la salida de comandos. Usa códigos de salida para indicar el éxito y el fallo, y comprueba archivos, texto y números para decidir qué hacer a continuación. Repite tareas con bucles for, while y until, y pasa argumentos para que un mismo guion resuelva muchos casos. Por último, programa la ejecución automática de tus guiones con cron o temporizadores de systemd y comprueba que cada ejecución haya terminado correctamente.

PrincipianteUnidad 4 de 7 del curso Curso de Introducción a Linux

Lo que aprenderás

  1. Convierte una secuencia de comandos que escribes una y otra vez en un archivo de guion, comienza con la línea de intérprete adecuada y ejecútalo desde cualquier directorio.
    • Convierte comandos repetidos en un archivo de guion
      Escribe comandos en orden en un archivo de texto sin formato, añade comentarios y comienza el archivo con una línea de intérprete que indique Bash como intérprete.
    • Ejecuta un guion y elige dónde guardarlo
      Haz que un guion sea ejecutable, ejecútalo mediante su ruta o un intérprete, colócalo en un directorio incluido en PATH y aprende cuándo puede modificar tu intérprete de comandos actual.
  2. Guarda texto, números y salidas de comandos en variables, lee la entrada del usuario y usa comillas para que los espacios y caracteres especiales lleguen intactos a los comandos.
    • Crea, lee y exporta variables
      Asigna y usa variables del intérprete de comandos, elige buenos nombres, lee la entrada del usuario y pasa variables a los programas que inicia un guion.
    • Protege palabras, variables y caracteres especiales mediante comillas
      Elige entre comillas simples, comillas dobles y barras invertidas, y protege cada expansión de variable con comillas para que los espacios y comodines de los valores no alteren un comando.
    • Captura la salida de comandos y realiza cálculos con números enteros
      Almacena la salida de un comando mediante sustitución de comandos y realiza operaciones con números enteros, por ejemplo para crear nombres de archivo con fecha y mantener contadores.
  3. Lee y establece el estado de salida de comandos y guiones, encadena comandos según su éxito o fallo, y detecta y detiene errores antes de que causen daños.
    • Lee y establece códigos de salida y encadena comandos según sus resultados
      Usa el estado de salida que devuelve cada comando, termina un guion con un código significativo y ejecuta comandos solo cuando uno anterior haya tenido éxito o haya fallado.
    • Detecta errores y detén un guion de forma segura
      Comprueba y traza un guion para detectar errores, envía mensajes de error a la salida de error estándar y haz que el guion se detenga ante fallos, variables no establecidas y cadenas de comandos que fallen.
  4. Comprueba archivos, texto y números, elige qué hacer con if y case, y repite comandos sobre listas, archivos y líneas con bucles for, while y until.
    • Realiza pruebas con archivos, cadenas y números
      Escribe condiciones con test, [ ] y [[ ]] que comprueben si existen archivos, comparen texto y comparen números enteros, y combínalas o niégalas.
    • Elige acciones con if, elif, else y case
      Ejecuta distintos comandos según una condición con if, elif y else, y compara un valor con varios patrones mediante case.
    • Repite comandos sobre listas y archivos con for
      Recorre una lista de palabras, los archivos que coinciden con un patrón, un rango de números o los argumentos de un guion, y maneja nombres de archivo con espacios.
    • Repite tareas hasta que cambie una condición con while y until
      Ejecuta comandos mientras una condición tenga éxito o hasta que lo tenga, lee un archivo línea por línea y controla los bucles con break, continue y sleep.
  5. Proporciona la entrada de un guion en la línea de comandos, lee los argumentos dentro del guion, compruébalos y proporciona valores predeterminados para que el mismo guion funcione en muchos casos.
    • Lee los parámetros posicionales y el número de argumentos
      Usa $0, de $1 a $9, ${10}, $# y "$@" para leer las palabras que se indican después del nombre de un guion, y usa shift para recorrerlas.
    • Comprueba argumentos, muestra instrucciones de uso y establece valores predeterminados
      Valida el número y el tipo de argumentos, muestra un mensaje de uso y termina con un código de error, usa valores predeterminados y gestiona opciones sencillas.
  6. Ejecuta guiones a horas o intervalos fijos sin tener una sesión abierta, con cron o temporizadores de systemd, y comprueba que las ejecuciones programadas se produzcan y terminen correctamente.
    • Programa tareas con cron
      Escribe entradas de crontab con los cinco campos de tiempo, edítalas y enuméralas con crontab, y prepara los guiones para el entorno mínimo de cron.
    • Programa tareas con temporizadores de systemd
      Asocia una unidad de servicio con una unidad de temporizador, escribe programaciones de calendario y de intervalos, habilita el temporizador y comprueba la próxima ejecución y los registros.

Guía de estudio de Guiones de Bash

6 capítulos

1

Escribe y ejecuta tus primeros guiones de Bash

Es más fácil repetir unos cuantos comandos cuando están en un mismo guion. Asignarás al archivo un intérprete de Bash, mantendrás sus instrucciones legibles y elegirás cómo iniciarlo. Los permisos de archivos, las rutas de búsqueda de comandos y los intérpretes hijos explican varias sorpresas habituales: por qué un guion funciona con bash pero falla con ./, por qué no se encuentra su nombre y por qué sus cambios de directorio no desplazan tu terminal.

1.1 Convierte comandos repetidos en un archivo de guion

Un guion del intérprete de comandos guarda una secuencia de comandos en un archivo de texto sin formato. Bash lee los comandos en orden, igual que lee los que introduces en un indicador de comandos. Un guion puede repetir una tarea sin que alguien escriba cada paso y te proporciona un único lugar donde corregirla o mejorarla.

Pon el intérprete en la primera línea

La línea de intérprete indica a Linux qué programa debe leer un guion ejecutable. Comienza un guion de Bash con #!/bin/bash. Los caracteres #! deben ser los dos primeros del archivo: no debe haber espacios ni una línea en blanco antes de ellos. Bash es Bourne Again Shell. Se usa ampliamente como intérprete de comandos interactivo en Linux y también lee archivos de guion.

Un intérprete es un programa que lee y ejecuta otro lenguaje. El mismo mecanismo permite que #!/usr/bin/python3 seleccione Python o que #!/usr/bin/awk -f seleccione awk. El resto de un guion de Bash debe contener comandos que Bash entienda.

Crea backup-notes.sh en un editor de texto sin formato como nano o vi:

#!/bin/bash
# Keep a copy of the notes and show the backup folder.
mkdir -p ~/backup
cp ~/notes.txt ~/backup/
ls -l ~/backup

Bash primero crea el directorio de destino, después copia las notas y luego lista el destino. mkdir -p también tiene éxito cuando el directorio ya existe, por lo que una ejecución posterior puede reutilizarlo. El archivo de origen ~/notes.txt debe existir para que la copia funcione. Guardar los comandos no crea ese archivo de origen.

Haz que las personas puedan leer el archivo

La segunda línea es un comentario. Fuera del texto protegido por comillas, # inicia un comentario al principio de una palabra; Bash ignora el resto de esa línea. Escribe comentarios sobre el propósito de un paso, por ejemplo por qué debe conservarse una copia de seguridad. Las líneas en blanco y la sangría facilitan la identificación de grupos de comandos. Mantén una sangría coherente a medida que añadas condiciones y bucles.

La terminación .sh ayuda a reconocer un guion del intérprete de comandos. Linux no exige esa terminación y añadirla no selecciona Bash ni concede permiso de ejecución. Un archivo llamado backup-notes puede ejecutar los mismos comandos.

Ajusta el intérprete al lenguaje
Primera líneaCómo se elige el intérprete
#!/bin/bashUsa Bash en la ruta fija /bin/bash.
#!/usr/bin/env bashUsa env para buscar Bash mediante PATH.
#!/bin/shUsa sh del sistema, que puede ser otro intérprete de comandos.

En Debian y Ubuntu, /bin/sh normalmente selecciona dash. Las funciones de Bash como [[ ... ]] fallan ahí. Un guion de Bash necesita un intérprete de Bash aunque algunos comandos sencillos funcionen en ambos intérpretes. Llamar a un archivo something.sh no corrige una línea de intérprete inadecuada.

Reconoce un problema de finales de línea

Los editores de Windows pueden guardar un retorno de carro antes de cada salto de línea. En Linux, ese carácter invisible puede pasar a formar parte de la ruta de la línea de intérprete. Un error como /bin/bash^M: bad interpreter: No such file or directory señala este problema, aunque /bin/bash exista.

Convierte el archivo a finales de línea de Unix con dos2unix backup-notes.sh y guarda los futuros guiones con finales de línea de Unix en el editor. Los comandos del archivo pueden ser correctos y, aun así, el carácter adicional impedir que Linux inicie su intérprete.

Puntos clave

  • Un guion es texto sin formato que contiene comandos para ejecutar en orden.
  • La línea de intérprete debe comenzar al principio mismo del archivo e indicar el intérprete adecuado.
  • Usa comentarios y sangría para aclarar el propósito y la estructura.
  • La extensión .sh es una convención; no selecciona un intérprete de comandos.
  • Los finales de línea de Unix evitan que un retorno de carro oculto impida el funcionamiento de la línea de intérprete.

1.2 Ejecuta un guion y elige dónde guardarlo

Bash puede leer un guion directamente o iniciarlo como programa. Estas formas difieren en los permisos que necesitan y en cómo se elige el intérprete. La ruta que escribes también determina si el intérprete de comandos busca un comando o usa un archivo concreto.

Dos formas de iniciar el mismo archivo
bash backup-notes.sh
chmod u+x backup-notes.sh
./backup-notes.sh

El primer comando inicia Bash y le pide que lea el archivo. El guion necesita permiso de lectura; no requiere su propio bit de ejecución. Bash trata la línea de intérprete como un comentario porque el intérprete ya se ha elegido.

El segundo comando añade permiso de ejecución para el propietario del archivo. En una cadena de permisos como -rwxr--r--, la x del propietario indica que es ejecutable. El tercer comando ejecuta el archivo como programa y usa su línea de intérprete. chmod +x también es habitual; si no se indica una clase de permisos, umask limita qué clases reciben permiso de ejecución. chmod u+x selecciona explícitamente al propietario.

Si ./backup-notes.sh informa «Permission denied», comprueba el permiso de ejecución y el acceso a la ruta. Que bash backup-notes.sh funcione no demuestra que la ejecución directa tenga los permisos necesarios.

Comprende la búsqueda de comandos

./ significa el directorio actual. Cuando un comando contiene una barra, Bash sigue esa ruta. Cuando escribes un nombre sin barra, Bash busca en los directorios de PATH. El directorio actual normalmente no está en esa lista, por lo que estar dentro del directorio de un guion no basta para ejecutarlo solo por su nombre.

echo "$PATH"
command -v backup-notes.sh
type backup-notes.sh

PATH es una lista separada por dos puntos, como /home/sam/.local/bin:/usr/local/bin:/usr/bin:/bin. Se usa el primer ejecutable que coincide. Los dos últimos comandos ayudan a identificar qué se ejecutará para un nombre, incluida una copia más antigua en otro lugar de PATH.

Para que un guion personal esté disponible por su nombre, colócalo en un directorio de tu PATH. Muchas distribuciones añaden ~/bin o ~/.local/bin al iniciar sesión si ese directorio existe; comprueba tu PATH real. /usr/local/bin es una ubicación habitual para guiones compartidos por los usuarios y requiere permisos de administrador para escribir en él.

Elige entre un intérprete hijo y el intérprete actual

Ejecutar ./settings.sh o bash settings.sh inicia un proceso hijo de Bash. Sus variables y cambios de directorio pertenecen a ese proceso hijo. Un guion que contiene cd /var/log no desplaza el terminal que lo inició. Cuando termina, sigues en el directorio original del terminal.

La ejecución de un archivo en el intérprete actual (sourcing) lee comandos en el intérprete actual:

source ./settings.sh
# Equivalent short form:
. ./settings.sh

Úsala para un archivo de configuración destinado a cambiar tu sesión. Esta forma de ejecución necesita permiso de lectura, no de ejecución, y la línea de intérprete no inicia un intérprete separado. Por tanto, ejecutar así un archivo de configuración de Bash presupone que el intérprete actual entiende la sintaxis de Bash.

Lee el resultado de una ejecución

Inmediatamente después de que termine un guion, echo $? muestra su estado de salida. Salvo que el guion use exit con un código elegido, su estado procede del último comando. Por tanto, un listado final correcto puede ocultar una copia que falló antes; las comprobaciones de errores que verás más adelante permitirán que el guion indique el resultado real de la tarea.

Puntos clave

  • bash file lee un guion con Bash; ./file necesita permiso de ejecución y usa la línea de intérprete.
  • Solo se busca en PATH para nombres de comandos sin barra.
  • Comprueba un nombre de comando con command -v o type.
  • La ejecución inicia un intérprete hijo; ejecutar un archivo en el intérprete actual puede modificarlo.
2

Almacena valores en variables y protégelos con comillas de forma segura

Las variables permiten que los mismos comandos funcionen con rutas, nombres y recuentos cambiantes. La protección mediante comillas mantiene esos valores intactos mientras Bash construye una línea de comandos, de modo que un espacio en un nombre siga formando parte de él. Leerás entradas, pasarás valores a programas hijos, capturarás la salida de comandos y calcularás con números enteros. Estos elementos funcionan juntos cuando un guion crea un nombre de archivo con fecha o mantiene un recuento acumulado.

2.1 Crea, lee y exporta variables

Una variable da un nombre a un valor para que el mismo guion pueda reutilizarlo. Las variables de Bash normalmente contienen texto, incluso cuando ese texto parece un número. Asignas el valor una vez y expandes el nombre dondequiera que un comando necesite ese valor.

Asigna sin espacios
city=Lisbon
greeting="Good morning"
echo "$greeting from $city"

La salida es «Good morning from Lisbon». No hay espacios alrededor del = de asignación. En city = Lisbon, Bash trata city como un comando y las demás palabras como argumentos. Las comillas alrededor de "Good morning" mantienen ambas palabras en un solo valor.

Usa letras, dígitos y guiones bajos en los nombres de variables, con una letra o un guion bajo al principio. Los nombres distinguen entre mayúsculas y minúsculas: file, File y FILE son distintos. Elige nombres en minúsculas como backup_dir para los valores propios de tu guion. Esto ayuda a evitar que se sustituyan variables de entorno como PATH o HOME. Establecer PATH=/data cambia la resolución de comandos y puede hacer que dejen de encontrarse comandos habituales.

Indica dónde termina un nombre

Un signo de dólar introduce una expansión. Las llaves muestran el límite cuando sigue más texto inmediatamente:

file=report
echo "${file}_old"

Esto muestra «report_old». Con "$file_old", Bash busca una variable llamada file_old, no file seguido de _old. Sin set -u, un nombre no establecido se expande a texto vacío. Por tanto, un error de escritura puede producir una ruta o un mensaje vacío sin un error inmediato.

Un valor como count=5 almacena el texto «5». Añadir texto junto a una expansión no calcula: echo "$count+1" muestra «5+1». La expansión aritmética da a los números una función diferente cuando se necesitan cálculos.

Lee una línea de entrada
read -r -p "Your name: " name
echo "Hello, $name"

read almacena la línea introducida en name. -p proporciona la indicación y -r conserva las barras invertidas. Con la entrada «Lee Kim», el saludo es «Hello, Lee Kim». Un guion ejecutado sin una persona presente necesita obtener su entrada de argumentos, archivos o valores predeterminados; una indicación no puede proporcionar de forma fiable un valor que falta.

Exporta valores para programas hijos

Una variable ordinaria del intérprete de comandos pertenece al intérprete donde se establece. La exportación la marca para incluirla en el entorno que se copia a los programas que inicia ese intérprete:

export BACKUP_DIR=/mnt/usb
bash backup-notes.sh

El proceso hijo de Bash puede ahora leer BACKUP_DIR. Si ese proceso hijo asigna otro valor, el proceso padre conserva el suyo. La herencia del entorno va del padre al hijo; no envía los cambios posteriores de vuelta al padre.

NombreSignificado habitual
HOMEDirectorio personal
USERNombre de usuario
PWDDirectorio de trabajo actual
PATHDirectorios donde se buscan nombres de comandos

env o printenv muestra las variables de entorno. unset name elimina la variable llamada name; no asigna una cadena vacía. Con una expansión normal ambas pueden parecer vacías, pero una comprobación de variables no establecidas puede distinguir una variable ausente de una establecida.

Puntos clave

  • Las asignaciones usan name=value sin espacios alrededor de =.
  • Los nombres de variables distinguen entre mayúsculas y minúsculas; usa nombres en minúsculas para tus propios valores.
  • ${name} marca el final del nombre de una variable antes del texto contiguo.
  • read -r lee la entrada y conserva las barras invertidas.
  • Los valores exportados se copian a los procesos hijos, nunca de vuelta a un proceso padre.
  • unset elimina una variable.

2.2 Protege palabras, variables y caracteres especiales mediante comillas

Bash lee un comando antes de que el programa reciba sus argumentos. Los espacios separan palabras y caracteres como *, ?, $, ;, &, |, < y > tienen funciones especiales. La protección mediante comillas controla cuáles de esas funciones permanecen activas.

Elige qué debe expandirse
FormaQué hace Bash
'fixed text'Mantiene como literal todo lo que contiene.
"text with $name"Conserva los espacios y caracteres comodín, pero expande variables, salidas de comandos y operaciones aritméticas.
\*Trata literalmente el siguiente carácter fuera de comillas.

Con HOME=/home/sam, compara:

echo 'Home: $HOME *'
echo "Home: \$HOME *"

El primero muestra «Home: $HOME *». El segundo muestra «Home: /home/sam *». El asterisco permanece literal en ambos, pero solo las comillas dobles permiten que la variable se expanda. Una comilla simple no puede colocarse directamente dentro de una cadena protegida por comillas simples.

Dentro de comillas dobles, las barras invertidas pueden proteger un signo de dólar, un acento grave, una comilla doble o una barra invertida. Por ejemplo, echo "Price: \$5" muestra «Price: $5». Fuera de comillas, echo 5 \* 3 muestra «5 * 3» y touch my\ file.txt crea un archivo con un espacio en su nombre.

Sigue un valor sin comillas por Bash
file="my report.txt"
cp $file backup/

Primero Bash expande la variable. Después, la división en palabras divide su valor en espacios, tabulaciones y saltos de línea. El comando recibe my, report.txt y backup/ como argumentos separados. Intenta copiar dos archivos de origen en lugar del único archivo deseado.

Si una palabra resultante contiene caracteres comodín, la expansión de nombres de archivo la sustituye después por los nombres coincidentes. Un valor almacenado como *.txt puede convertirse en varios argumentos de archivo al expandirse sin comillas. Estos pasos adicionales ocurren antes de que comience cp; el programa no puede recuperar la agrupación que pretendías.

cp "$file" backup/

Ahora el valor expandido sigue siendo un argumento, «my report.txt». Bash elimina los propios caracteres de comillas; son instrucciones para el análisis, no parte de la ruta que se pasa a cp. Pon comillas dobles alrededor de las expansiones de variables y las sustituciones de comandos siempre que su valor completo deba permanecer unido.

Conserva un valor vacío

Las comillas también importan cuando un valor está vacío. En [ $answer = yes ], un answer vacío desaparece y deja una prueba no válida. [ "$answer" = yes ] pasa una cadena vacía como un argumento, por lo que la prueba es válida y falsa.

La misma regla de agrupación se aplica a palabras literales. mkdir new folder crea dos directorios, mientras que mkdir "new folder" crea uno. Proteger una ruta completa con comillas es útil tanto si su espacio se escribió directamente como si procede de una variable.

Combina texto literal y expandido

Las partes contiguas protegidas por comillas sin un espacio que las separe forman una sola palabra. Con price=8, echo 'Price: $'"$price" muestra «Price: $8». La parte fija está entre comillas simples y la parte variable entre comillas dobles. Un patrón de búsqueda también puede mantenerse fijo: grep 'cost: \$[0-9]' prices.txt pasa su patrón sin expansión por el intérprete de comandos y deja que grep lo interprete.

Puntos clave

  • Las comillas simples mantienen el texto literal; las dobles permiten expansiones y mantienen unidos los valores.
  • Las expansiones sin comillas pasan por la división en palabras y después por la expansión de nombres de archivo.
  • Las comillas conservan un valor vacío como argumento.
  • Una barra invertida puede hacer que un carácter especial se trate literalmente.
  • Las partes contiguas protegidas por comillas forman una palabra cuando ningún espacio las separa.

2.3 Captura la salida de comandos y realiza cálculos con números enteros

Los comandos suelen producir un valor que necesita otro paso. Bash puede capturar esa salida, colocarla dentro de un texto o usarla en un cálculo. La sustitución de comandos y la expansión aritmética tienen una puntuación similar, pero realizan tareas distintas.

Captura la salida estándar
today=$(date +%F)
cp notes.txt "notes-${today}.txt"

$(...) ejecuta un comando y sustituye la expresión por su salida estándar. El 2026-10-22, today contiene «2026-10-22» y la copia se llama notes-2026-10-22.txt. Una fecha en orden año-mes-día mantiene los nombres de archivo ordenados por fecha cuando se ordenan por nombre. También puedes poner la sustitución directamente en el nombre: "notes-$(date +%F).txt".

Los caracteres de salto de línea finales se eliminan de la salida capturada. La forma más antigua con acentos graves también captura la salida, pero $(...) es más fácil de leer y anidar. Protege con comillas una sustitución usada como argumento de un comando, como "$(date +%F)", para mantener unido su resultado.

La sustitución de comandos captura solo la salida estándar. Los errores enviados a la salida de error estándar siguen yendo a su destino habitual. result=$(some_command 2>&1) combina ambos flujos dentro de la captura cuando eso es lo que necesita el guion. Mezclar errores en un valor destinado a contener un número haría fallar los cálculos posteriores.

Captura un recuento sin nombre de archivo
lines=$(wc -l < access.log)
echo "Lines: $lines"

Si el archivo contiene 342 caracteres de salto de línea, wc proporciona el recuento 342. Al redirigir el archivo a wc, su salida contiene solo el recuento; wc -l access.log también muestra el nombre del archivo. Un resultado que parece numérico puede reutilizarse después, siempre que el comando haya tenido éxito.

Calcula con números enteros

$(( ... )) realiza una expansión aritmética:

echo "$(( 17 / 5 ))"
echo "$(( 17 % 5 ))"

Los resultados son 3 y 2. La división entera descarta el resto; % lo devuelve. La suma, la resta y la multiplicación usan +, - y *. Los nombres de variables pueden aparecer sin signo de dólar dentro de la expresión: total=$(( price * qty )).

Con a=5, echo "$a+3" muestra «5+3» como texto. echo "$(( a + 3 ))" calcula y muestra 8. Los paréntesis adicionales seleccionan la aritmética; $(a + 3) intentaría ejecutar un comando llamado a.

Un contador comienza con un valor como count=0 y se actualiza con count=$(( count + 1 )). Bash también ofrece (( count++ )); este es un comando aritmético con su propio estado de salida, que importa en guiones que usan opciones de tratamiento de errores.

Conserva la precisión necesaria

La aritmética de Bash usa números enteros. 7 / 2 da 3 y un valor decimal como 2.5 provoca un error de sintaxis aritmética. Una herramienta independiente puede calcular decimales:

echo "scale=2; 7 / 2" | bc

Esto produce 3.50. En la aritmética entera, multiplica antes de dividir cuando el producto conserve una fracción que aún necesitas. Para 45 de 60, $(( 45 * 100 / 60 )) da 75. Dividir primero da cero para 45 / 60, por lo que $(( 45 / 60 * 100 )) sigue siendo cero; la fracción perdida no puede recuperarse mediante una multiplicación posterior.

Puntos clave

  • $(command) captura la salida estándar y elimina los saltos de línea finales.
  • $((expression)) calcula con números enteros.
  • Usa / para la división entera y % para su resto.
  • Un contador almacena su valor actualizado después de cada incremento.
  • Multiplicar antes de dividir puede evitar una pérdida temprana de precisión en la aritmética entera.
  • Usa una herramienta como bc cuando se necesite un resultado decimal.
3

Indica el éxito y el fallo mediante códigos de salida

Un guion necesita un resultado que tanto las personas como los programas puedan entender. La salida impresa explica lo que ocurrió, mientras que un estado de salida permite que otro comando decida si debe continuar. Guardarás ese estado, comprobarás los pasos dependientes y mantendrás visibles los fallos de las cadenas de comandos conectados por tuberías. Las comprobaciones de sintaxis, los trazados de ejecución y las opciones de tratamiento de errores ayudan a encontrar la causa de una ejecución fallida antes de que los comandos posteriores hagan más difíciles de ver sus efectos.

3.1 Lee y establece códigos de salida y encadena comandos según sus resultados

Un comando comunica su resultado de dos formas: puede mostrar texto y devuelve un estado de salida. Los programas usan ese estado para decidir qué ocurre después. Un guion puede mostrar un mensaje tranquilizador y aun así haber fallado, o no mostrar nada y tener éxito.

Lee un estado antes de que cambie

Un estado de salida es un número entero entre 0 y 255. Cero significa éxito. Un valor distinto de cero indica un fallo u otro resultado documentado. grep, por ejemplo, usa 0 para una coincidencia, 1 si no hay coincidencias y 2 para un error. Una búsqueda sin coincidencias puede ser un resultado normal para tu tarea aunque su estado sea distinto de cero.

$? contiene el estado del comando más reciente:

grep -q root /etc/passwd
status=$?
echo "Search status: $status"

La asignación guarda el resultado antes de que otro comando lo sustituya. En ls /missing; echo $?; echo $?, GNU ls devuelve 2 para la ruta inaccesible indicada en la línea de comandos. El primer echo muestra 2 y después termina correctamente. El segundo muestra 0, el estado de ese echo, no el del listado original.

Termina con un resultado útil

exit 1 termina inmediatamente un guion y comunica 1 a quien lo llamó. exit 0 comunica éxito. Un exit sin número usa el estado del comando anterior; llegar al final normalmente usa el estado del último comando. Elige códigos entre 0 y 255: exit 256 vuelve a 0 e indicaría incorrectamente que hubo éxito.

Algunos estados proceden del propio Bash:

CódigoSignificado
127No se encontró el comando.
126Se encontró el comando, pero no se pudo ejecutar.
128 + nEl comando terminó debido a la señal número n.

Ctrl+C envía la señal 2, por lo que un comando terminado de esa forma suele comunicar 130. Los programas ordinarios también documentan sus propios códigos; 1 y 2 no tienen un significado universal para todas las herramientas.

Encadena comandos dependientes
mkdir -p ~/backup && cp notes.txt ~/backup/
cd /data/reports || exit 1

&& ejecuta el siguiente comando solo después de un éxito. Aquí la copia depende de crear o encontrar el directorio de copia de seguridad. || ejecuta el siguiente comando solo después de un fallo. Aquí, un cambio de directorio fallido detiene el guion antes de que los comandos posteriores usen el directorio de trabajo equivocado.

true devuelve 0; false devuelve 1. Un ! inicial invierte el éxito o el fallo de un comando. ! grep -q ERROR app.log tiene éxito cuando la búsqueda no encuentra ninguna línea coincidente, aunque también tiene éxito si grep falla con un error; usa comprobaciones explícitas del estado cuando debas distinguir esos resultados.

Comprueba una cadena de comandos completa
grep ERROR missing.log | wc -l

De forma predeterminada, una cadena de comandos conectados por tuberías tiene el estado de su último comando. grep falla porque falta el archivo, pero wc lee un flujo vacío, muestra 0 y tiene éxito. Por tanto, el estado de la cadena es 0.

set -o pipefail hace que una cadena falle cuando falle cualquiera de sus comandos. Devuelve el estado distinto de cero situado más a la derecha, o 0 si todos los comandos tienen éxito. Esto hace que los errores de los comandos anteriores sean visibles para if, &&, || y quien llamó al guion. Así, un programador de tareas puede distinguir un informe correcto de uno que nunca leyó su entrada.

Puntos clave

  • El estado de salida 0 significa éxito; los resultados distintos de cero tienen significados documentados por cada programa.
  • Guarda $? inmediatamente si necesitas usarlo después de otro comando.
  • exit proporciona un resultado a quien llamó al guion.
  • && continúa después de un éxito y || continúa después de un fallo.
  • Sin pipefail, una cadena de comandos conectados por tuberías solo comunica el estado de su último comando.

3.2 Detecta errores y detén un guion de forma segura

Bash normalmente continúa después de que falle un comando. Si el siguiente comando depende de ese trabajo, continuar puede convertir un pequeño fallo en un problema mayor. Comprueba explícitamente los pasos de los que dependen otros y usa la comprobación de sintaxis y el trazado para averiguar por qué una ejecución se comporta de forma distinta a la prevista.

Detén el guion antes de que se propaguen los efectos de un fallo
cd /backups || exit 1

Ahora, los comandos posteriores solo pueden ejecutarse si el cambio de directorio tiene éxito. Esto importa antes de las operaciones con archivos: si falla un cambio de directorio y el guion continúa, las rutas relativas siguen apuntando al directorio anterior. Comprueba el destino antes de ejecutar comandos que modifiquen o eliminen archivos.

Un mensaje de error y un estado de fallo sirven a destinatarios distintos:

echo "Error: $file not found" >&2
exit 1

El mensaje va a la salida de error estándar, dejando la salida estándar disponible para los datos. Con ./report.sh > report.txt, el mensaje sigue siendo visible en el terminal mientras la salida normal entra en el archivo. El estado distinto de cero permite que otro programa detecte el error sin leer la frase.

Comprueba la sintaxis y después traza la ejecución
ComandoQué hace
bash -n script.shLee la sintaxis sin ejecutar comandos.
bash -x script.shEjecuta el guion y muestra los comandos expandidos antes de ejecutarlos.

La ausencia de fi, done o una comilla de cierre es un problema de sintaxis. bash -n puede localizarlo, a menudo mediante un mensaje «unexpected end of file». Una ruta de archivo válida desde el punto de vista sintáctico, pero mal escrita, necesita una comprobación durante la ejecución.

El trazado antepone + a los comandos. Una línea como cp "$src" "$dest" revela las rutas reales que recibió. set -x y set +x activan y desactivan el trazado alrededor de una sección.

Comprende las opciones de tratamiento de errores

set -euo pipefail combina tres controles:

  • -e termina el guion después de un fallo de comando no tratado.
  • -u informa del uso de una variable no establecida como un error.
  • pipefail hace que los comandos fallidos de una cadena conectada por tuberías afecten a su estado.

-e permite fallos esperados en las condiciones de if, while y until, en comandos negados y en comandos que no son los últimos de listas con && o ||. Sin pipefail, un fallo anterior al último comando de la cadena no provoca la salida. Las comprobaciones explícitas siguen siendo útiles porque indican qué debe hacer el guion cuando falla un paso concreto.

Un comando aritmético también comunica verdadero o falso. (( count++ )) devuelve el estado 1 cuando el valor anterior es 0, por lo que un uso no tratado con -e puede detener el guion aunque se haya producido el incremento. La asignación count=$(( count + 1 )) evita ese estado del comando aritmético.

-u detecta un error de escritura como $filname cuando solo se ha establecido filename. No rechaza una variable que existe pero está vacía. ${dir:?not set} comprueba si dir falta o está vacía en esa expansión. Un resultado esperado sin coincidencias puede gestionarse con una prueba; command || true suprime todos los fallos de ese comando, por lo que debes usarlo solo cuando todos esos fallos sean aceptables.

Lee los mensajes y limpia los archivos temporales

«Command not found» señala un problema con el nombre, el programa instalado o PATH. «Permission denied» señala un problema de ejecución o de acceso a un archivo. «Unary operator expected» suele deberse a un valor vacío sin comillas en [ ]; «integer expression expected» significa que una prueba numérica recibió texto.

Un manejador de eventos EXIT establece una limpieza, por ejemplo trap 'rm -f "$tmpfile"' EXIT, después de asignar tmpfile. El comando entre comillas se ejecuta cuando Bash termina, incluso con un exit explícito o una salida por error con -e. ShellCheck también puede inspeccionar guiones en busca de errores habituales de protección mediante comillas y de lógica antes de ejecutarlos.

Puntos clave

  • Comprueba un paso antes de ejecutar comandos que dependan de él.
  • Escribe los mensajes de diagnóstico en la salida de error estándar e indica el fallo con un estado distinto de cero.
  • bash -n comprueba la sintaxis; bash -x ejecuta y traza.
  • set -e tiene excepciones para los fallos que se comprueban.
  • set -u detecta variables no establecidas, mientras que ${name:?message} también rechaza valores vacíos.
  • Un manejador EXIT puede eliminar un archivo temporal cuando termina el guion.
4

Toma decisiones y repite tareas

Un guion útil elige acciones y las repite sobre entradas cambiantes. Las pruebas convierten preguntas sobre archivos, texto y números en resultados de éxito o fallo. Las ramas seleccionan una acción, mientras que los bucles aplican comandos a listas o continúan hasta que cambia una condición. Seguirás el valor usado en cada iteración y conservarás espacios, registros y contadores a medida que los datos pasen por el guion.

4.1 Realiza pruebas con archivos, cadenas y números

Una condición en Bash es un comando cuyo estado significa verdadero o falso. Las pruebas permiten hacer preguntas sobre rutas, texto y números. Elige un operador para el tipo de valor que tienes; los mismos caracteres mostrados pueden tener distintos significados como texto y como número.

Separa los elementos de la prueba

test -f notes.txt y [ -f notes.txt ] preguntan si una ruta apunta a un archivo regular existente. [ es un comando y su último argumento debe ser ]. Los espacios separan sus argumentos:

[ -f "$file" ]

Sin el espacio después de [, Bash puede buscar un comando llamado [-f. En [ "$a"="$b" ], la falta de espacios alrededor de = forma una sola palabra no vacía, cuya prueba da verdadero aunque los valores sean distintos. Los operadores deben ser argumentos separados.

Elige una prueba de archivo
OperadorVerdadero cuando la ruta…
-eExiste.
-fEs un archivo regular existente.
-dEs un directorio existente.
-r, -w, -xEl usuario actual puede leerla, escribir en ella o ejecutarla, respectivamente.
-sExiste y tiene un tamaño mayor que cero.
-LEs un enlace simbólico.

Para un directorio llamado logs, -e y -d tienen éxito, mientras que -f falla. Las pruebas de archivos normalmente siguen un enlace simbólico hasta su destino; -L comprueba el propio enlace. Por tanto, un enlace roto puede satisfacer -L y fallar en -e.

Compara texto o números enteros

Las pruebas de cadenas usan = y != para comprobar la igualdad y la desigualdad. -z comprueba si la longitud es cero y -n si es distinta de cero. [ "$answer" = yes ] coincide exactamente con «yes»; «Yes» y «yes » son textos distintos. Las comillas dobles mantienen un valor vacío en la prueba.

Las comparaciones de enteros usan -eq, -ne, -lt, -le, -gt y -ge: igual, distinto, menor que, menor o igual que, mayor que y mayor o igual que. [ "$count" -gt 100 ] pregunta si el número supera 100.

[ 07 -eq 7 ]
[ 07 = 7 ]

La comparación numérica tiene éxito porque los valores son iguales. La comparación de cadenas falla porque uno de los textos empieza con un cero adicional.

No uses > sin protección para una prueba numérica dentro de [ ]. En [ 10 > 9 ], Bash redirige la salida a un archivo llamado 9 y comprueba la palabra no vacía que queda. En [[ 10 < 9 ]] de Bash, el operador compara cadenas, por lo que el carácter inicial 1 se ordena antes que 9. Usa -lt o -gt para comparaciones numéricas, o aritmética de Bash como (( count > 100 )).

Combina condiciones

[ ! -d "$dir" ] tiene éxito cuando la ruta no es un directorio existente; puede ser un archivo regular o no existir. [ -f "$f" ] && [ -r "$f" ] tiene éxito solo cuando ambas pruebas tienen éxito. Las pruebas separadas y unidas por || tienen éxito cuando al menos una lo tiene.

Bash también tiene la palabra clave condicional [[ ... ]]. Evita la división en palabras de sus expansiones de variables y permite && y || en su interior. Un patrón sin comillas a la derecha de == busca coincidencias con el patrón: [[ $file == *.log ]] coincide con «app.log». Proteger ese patrón con comillas haría que se tratara literalmente. Esta sintaxis necesita Bash; dash no la implementa.

Puntos clave

  • Una prueba indica verdadero con el estado 0 y falso con el estado 1.
  • Pon espacios alrededor de [ y sus operadores, y cierra con ].
  • Las pruebas de archivos distinguen entre existencia, tipo y acceso.
  • La igualdad de cadenas compara texto; los operadores numéricos comparan valores enteros.
  • Usa -gt y -lt para números, no símbolos de redirección sin protección.
  • La negación invierte una prueba; && requiere que se cumplan ambas condiciones.
  • [[ ... ]] de Bash admite patrones y evita la división en palabras.

4.2 Elige acciones con if, elif, else y case

Las condiciones resultan útiles cuando seleccionan acciones. Un bloque if elige una rama a partir de los resultados de comandos. Un bloque case selecciona una rama comparando un valor con patrones. Ambos muestran las acciones disponibles en el guion.

Deja que un comando elija una rama
if grep -q ERROR app.log; then
  echo "Errors found"
else
  echo "No successful match"
fi

if ejecuta el comando y entra en la primera rama cuando devuelve 0. En caso contrario, entra en else. La propia búsqueda es la condición; no es necesario ejecutarla, mostrar algo y después examinar $?. Un error de grep también produce un valor distinto de cero, por lo que este ejemplo describe la rama else como ausencia de una coincidencia satisfactoria, no como prueba de que el archivo no contiene errores.

then debe comenzar un comando nuevo: colócalo en la línea siguiente o después de un punto y coma. fi cierra el bloque. La falta de fi suele producir un error de sintaxis al final del archivo porque Bash sigue esperando que se cierre el bloque.

Ordena las condiciones que se solapan

elif añade una prueba que se ejecuta solo cuando han fallado las pruebas anteriores. Para un porcentaje entero de uso del disco:

if [ "$usage" -ge 90 ]; then
  echo "CRITICAL: disk ${usage}% full"
elif [ "$usage" -ge 75 ]; then
  echo "WARNING: disk ${usage}% full"
else
  echo "OK: disk ${usage}% full"
fi

Con usage=82, la primera prueba falla y la segunda tiene éxito, lo que produce «WARNING: disk 82% full». Con 95, se ejecuta la primera rama y se omite la rama de advertencia. Si la prueba de 75 fuera primero, 95 coincidiría con ella y nunca llegaría a la prueba crítica. Ordena los rangos que se solapan de modo que se compruebe la condición más restrictiva.

Solo se ejecuta la primera rama cuya prueba tiene éxito. else no necesita condición y se ocupa de los casos restantes. Se puede omitir elif o else cuando la tarea no lo necesite.

Compara un valor con case
case "$1" in
  start) echo "Starting" ;;
  stop) echo "Stopping" ;;
  y|Y|yes) echo "Confirmed" ;;
  *) echo "Usage: $0 start|stop|y|Y|yes" >&2; exit 2 ;;
esac

Cada patrón termina con ), cada rama termina con ;; y esac cierra el bloque. El | dentro de un patrón ofrece alternativas. El * final es el patrón de coincidencia universal y debe ir al final porque coincide con cualquier valor.

case usa patrones de nombres de archivo, no expresiones regulares. *.jpg coincide con un valor que termina en .jpg. [0-9]* coincide con un valor cuyo primer carácter es un dígito; el * puede coincidir después con cualquier texto, por lo que también coincide con «7draft». No demuestra que todo el valor contenga solo dígitos.

Elige la estructura adecuada

Usa case cuando una entrada, como un subcomando o una respuesta, tenga varias formas identificadas. Usa if cuando las condiciones examinen cosas distintas, como si existe un archivo y si un recuento supera un límite. Una coincidencia con un patrón se refiere a los caracteres de un valor; una prueba de archivo se refiere a la ruta en el disco. Un nombre terminado en .log puede coincidir con un patrón aunque no exista ningún archivo con ese nombre.

Puntos clave

  • if elige una rama según el estado de salida de un comando; cualquier comando puede ser una condición.
  • Las pruebas elif se ejecutan solo después de que fallen las condiciones anteriores.
  • Ordena los umbrales que se solapan del más restrictivo al más amplio.
  • case selecciona el primer patrón coincidente y usa ;; para terminar cada rama.
  • Una coincidencia con un patrón no demuestra que exista un archivo.

4.3 Repite comandos sobre listas y archivos con for

Un bucle for proporciona un nuevo valor al mismo cuerpo de comandos en cada iteración. La lista puede contener palabras literales, nombres de archivo coincidentes, un rango de números o los argumentos del guion. Bash asigna un elemento de la lista a la variable del bucle antes de ejecutar el cuerpo.

Recorre una lista fija
for host in web1 web2 db1; do
  echo "Checking $host"
done

La primera iteración tiene host=web1, la segunda host=web2 y la tercera host=db1. El bucle muestra tres líneas. do abre el cuerpo y done lo cierra. La variable sigue disponible después del bucle y contiene el último valor asignado.

Un bucle también puede acumular un resultado:

total=0
for n in 4 8 15; do
  total=$(( total + n ))
done
echo "$total"

El total almacenado cambia de 0 a 4, después a 12 y luego a 27. Inicializa el total antes del bucle para que la primera suma tenga un valor inicial definido.

Recorre los archivos coincidentes
for f in *.log; do
  [ -f "$f" ] || continue
  gzip -- "$f"
done

Bash expande el patrón en nombres coincidentes antes de ejecutar el cuerpo del bucle. Cada nombre de archivo coincidente sigue siendo un elemento de la lista, incluso si contiene espacios. Proteger "$f" con comillas dentro del cuerpo mantiene unido ese elemento cuando se pasa a gzip. Aquí, la prueba de archivo regular también omite los directorios cuyo nombre termina en .log.

Con la configuración predeterminada de expansión de nombres de archivo de Bash, un *.log sin coincidencias permanece literal. Un bucle sin una comprobación se ejecutaría una vez sobre los caracteres *.log y el comando fallaría. [ -e "$f" ] || continue omite las rutas inexistentes; usa -f cuando solo quieras archivos regulares.

No construyas un bucle de nombres de archivo a partir de $(ls). Su salida es texto, por lo que la división en palabras puede convertir «my report.txt» en dos elementos de la lista. Un patrón de nombres de archivo ya proporciona los nombres con sus límites intactos.

Crea un nombre nuevo a partir de cada nombre anterior
for f in *.jpeg; do
  [ -f "$f" ] || continue
  mv -- "$f" "${f%.jpeg}.jpg"
done

${f%.jpeg} elimina la terminación .jpeg del valor. Para «beach day.jpeg», el destino pasa a ser «beach day.jpg». Los dos argumentos protegidos con comillas mantienen intactas ambas rutas. -- indica a mv que los argumentos posteriores son nombres, incluso si uno empieza por -. Usa un directorio de destino sin nombres que entren en conflicto al probar el ejemplo, ya que mv puede reemplazar un destino existente.

Recorre un rango contando

for i in {1..5} proporciona del 1 al 5. Bash expande las llaves antes de expandir las variables, por lo que {1..$n} no produce un rango de longitud variable. Para un límite almacenado, usa la forma aritmética:

for (( i = 1; i <= n; i++ )); do
  echo "$i"
done

La primera expresión inicializa el contador, la del medio lo comprueba antes de cada iteración y la última lo actualiza. for i in $(seq 1 "$n") también produce una lista de números para un límite entero positivo adecuado. La sustitución sin comillas es deliberada y proporciona números separados.

Para los argumentos, for arg in "$@" proporciona un elemento por cada argumento original. La forma más corta for arg; do significa lo mismo y también conserva los espacios dentro de cada argumento.

Puntos clave

  • Un bucle for ejecuta su cuerpo una vez por cada elemento de la lista.
  • Los patrones proporcionan nombres de archivo completos; protege con comillas la variable del bucle en el cuerpo.
  • Un patrón sin coincidencias permanece literal con la configuración predeterminada de Bash, así que comprueba los archivos en los bucles.
  • Evita los bucles de nombres de archivo construidos a partir de $(ls).
  • Los rangos entre llaves se fijan antes de expandir las variables; usa un bucle aritmético para un límite variable.
  • "$@" conserva los límites originales de los argumentos.

4.4 Repite tareas hasta que cambie una condición con while y until

Algunas repeticiones terminan cuando cambia una condición, no cuando se agota una lista. while y until comprueban la condición antes de cada iteración. El cuerpo de while se ejecuta mientras su condición tiene éxito; el de until se ejecuta mientras su condición falla. Cualquiera de los dos bucles puede ejecutarse cero veces.

Actualiza aquello de lo que depende la condición
i=1
while [ "$i" -le 3 ]; do
  echo "Attempt $i"
  i=$(( i + 1 ))
done

La condición primero encuentra 1, después 2 y luego 3. El cuerpo muestra esos tres números de intento y aumenta el contador cada vez. Después de actualizarlo a 4, la siguiente prueba falla y el bucle termina. Si faltara la actualización, i permanecería en 1 y el bucle seguiría ejecutándose. Ctrl+C detiene un bucle que se ejecuta en primer plano.

Para esperar a un archivo:

until [ -f /tmp/export.done ]; do
  sleep 5
done

Si el archivo ya existe, el cuerpo del bucle nunca se ejecuta. En caso contrario, sleep 5 hace una pausa de cinco segundos antes de la siguiente comprobación. Una pausa evita que el bucle compruebe continuamente y desperdicie tiempo de procesador.

Lee los registros como líneas
while IFS= read -r line; do
  echo "Host: $line"
done < hosts.txt

read proporciona una línea en cada iteración y devuelve un estado de fallo al final del archivo. IFS= conserva los espacios al principio y al final de la línea; -r conserva las barras invertidas. La redirección de entrada después de done proporciona datos a todo el bucle, no solo a su último comando.

Una línea como «web1 production» permanece como un solo valor. for line in $(cat hosts.txt) dividiría en espacios, tabulaciones y saltos de línea, tratando esas dos palabras como iteraciones separadas. Esa forma no puede conservar registros arbitrarios basados en líneas.

Conserva los cambios después del bucle

Una tubería que envía datos a un bucle, como cat hosts.txt | while read -r line; do ...; done, normalmente ejecuta el bucle en un proceso hijo en Bash. Un contador modificado allí se pierde para el proceso padre cuando termina el hijo. Redirige el archivo al bucle cuando los comandos posteriores necesiten sus valores acumulados:

count=0
while IFS= read -r line; do
  count=$(( count + 1 ))
done < hosts.txt
echo "$count"

Esto procesa las líneas terminadas en un salto de línea y conserva el recuento actualizado en el intérprete de comandos actual. Ninguna cadena de comandos crea un proceso hijo para el bucle.

Gestiona el último registro y las salidas anticipadas

Un archivo puede terminar con texto pero sin un salto de línea final. read almacena ese último texto, pero indica un fallo, por lo que un while read simple no entra en su cuerpo para ese registro. Añade una segunda prueba para aceptar el texto no vacío almacenado:

while IFS= read -r line || [ -n "$line" ]; do
  echo "Host: $line"
done < hosts.txt

break sale del bucle inmediatamente. continue omite los comandos restantes de la iteración actual y vuelve a comprobar la condición para la siguiente. Por tanto, un bucle while true necesita un break, un exit o una señal para terminar; puede servir para un menú que sale del bucle cuando la entrada es «q». En un bucle con contador, coloca una actualización antes de cualquier continue que de otro modo la omitiría, o esa iteración podría repetirse indefinidamente.

Puntos clave

  • while repite tras un éxito; until repite tras un fallo.
  • Ambos bucles comprueban la condición antes de entrar en sus cuerpos.
  • Actualiza un contador o introduce una pausa en un bucle de comprobación para que avance sin esperar consumiendo recursos.
  • IFS= read -r conserva los espacios y las barras invertidas en la entrada basada en líneas.
  • Redirige un archivo al bucle para conservar las variables modificadas en el intérprete de comandos actual.
  • Una prueba adicional de cadena no vacía conserva un registro final sin salto de línea.
  • break sale de un bucle; continue pasa a su siguiente iteración.
5

Pasa argumentos a los guiones

Los argumentos de la línea de comandos permiten que un guion sirva para muchas tareas sin editar su código. Leerás valores individuales, conservarás una lista completa de argumentos y procesarás las opciones iniciales. Antes de comenzar el trabajo, cuenta y valida las entradas, explica cómo llamar correctamente al guion y proporciona valores predeterminados para los valores opcionales. El resultado puede ejecutarse desde un indicador de comandos o sin supervisión, con mensajes claros y un estado de salida cuando la entrada no sea válida.

5.1 Lee los parámetros posicionales y el número de argumentos

Los argumentos convierten un guion con entrada fija en un comando reutilizable. Bash coloca las palabras que siguen al nombre del guion en parámetros posicionales. Sus límites los establece el intérprete de comandos que hace la llamada, por lo que las comillas importan tanto al llamar al guion como cuando este usa esos valores.

Identifica los parámetros
./backup.sh /home/sam/docs /mnt/usb

Dentro del guion, $0 es ./backup.sh, $1 es /home/sam/docs y $2 es /mnt/usb. $# es 2, el número de argumentos. El guion puede usar cp -r "$1" "$2" para copiar el directorio de origen al destino sin fijar ninguna de las dos rutas en el código.

$0 describe el nombre usado para iniciar el guion; no se cuenta en $#. Con ./greet.sh Ana "Lee Kim", el primer argumento es «Ana» y el segundo es «Lee Kim». Sin las comillas alrededor del segundo nombre, el guion recibiría tres argumentos.

Usa llaves después del noveno argumento

De $1 a $9 se nombran los primeros nueve parámetros posicionales. El décimo necesita ${10} y las posiciones posteriores siguen la misma forma. $10 significa la expansión de $1 seguida del carácter literal 0. Si el primer argumento es «Ana», $10 se convierte en «Ana0» incluso cuando existe un décimo argumento.

Un parámetro omitido se expande a texto vacío con la configuración normal. Con dos argumentos, falta $3; con set -u, expandirlo provoca un error de variable no establecida. Comprueba el número antes de leer las posiciones obligatorias o usa una expansión que proporcione un valor predeterminado.

Conserva todos los límites de los argumentos

Supón que un guion recibe "a b" y c. Compara:

ExpansiónPalabras que se pasan a otro comando
"$@"Dos: «a b» y «c».
"$*"Una: «a b c», con el separador habitual de espacio.
$@Tres: «a», «b» y «c» con la división normal.

"$@" es la opción habitual para pasar argumentos a otro comando:

for arg in "$@"; do
  echo "Argument: $arg"
done

El bucle se ejecuta dos veces para esa llamada, una por cada argumento original. Sin argumentos se ejecuta cero veces. Poner "$@" entre comillas dobles tiene un significado especial: cada parámetro posicional sigue siendo una palabra separada, por lo que las comillas no unen toda la lista en una palabra.

"$*" une los valores usando el primer carácter de IFS, que normalmente es un espacio. Esto puede ser útil para una sola cadena destinada a mostrarse, pero pierde los límites individuales que puede necesitar un comando posterior.

Procesa parámetros con shift

shift elimina el primer parámetro posicional, desplaza los posteriores y reduce $#. En la llamada de copia de seguridad, un desplazamiento hace que $1 pase a ser /mnt/usb y que el recuento pase a ser 1. shift 2 elimina los dos primeros parámetros a la vez.

Esto permite crear un bucle que examine $1, lo procese y después desplace los parámetros antes de la siguiente iteración. Comprueba que queden argumentos con [ "$#" -gt 0 ]; de lo contrario, el guion puede leer un valor ausente o intentar desplazar más argumentos de los disponibles. El desplazamiento no cambia $0 ni puede cambiar la lista de argumentos del intérprete de comandos padre que inició el guion.

Puntos clave

  • $0 es el nombre de invocación, mientras que $1 y los siguientes contienen argumentos.
  • $# cuenta los argumentos; los espacios protegidos por comillas se mantienen dentro de un argumento.
  • Usa ${10} para el décimo argumento; $10 es $1 seguido de 0.
  • "$@" conserva los argumentos por separado, mientras que "$*" los une.
  • shift elimina los parámetros iniciales y cambia las posiciones de los restantes.

5.2 Comprueba argumentos, muestra instrucciones de uso y establece valores predeterminados

Un guion debe asegurarse de que su entrada sea válida antes de empezar a trabajar. Comprueba el número de argumentos y después su significado. Las entradas opcionales pueden tener valores predeterminados; las entradas obligatorias ausentes necesitan un mensaje de diagnóstico claro y un estado de salida distinto de cero.

Explica la llamada esperada
if [ "$#" -ne 2 ]; then
  echo "Usage: $0 SOURCE DEST" >&2
  exit 2
fi

Esto comprueba el número antes de expandir $1 o $2, por lo que también funciona con set -u. El mensaje de uso va a la salida de error estándar. Las mayúsculas nombran valores que proporciona el usuario, [DEST] indicaría un destino opcional y FILE... significa uno o más argumentos de archivo. Una opción de ayuda como -h normalmente muestra las instrucciones de uso y termina con 0 porque pedir ayuda es un uso correcto.

El número de argumentos por sí solo no puede indicar si un origen es válido. [ -d "$1" ] comprueba si existe un directorio. Una prueba de archivo regular puede seleccionar archivos, pero la operación en sí sigue necesitando una comprobación del resultado: los permisos u otros errores pueden impedir la lectura.

Usa un valor predeterminado o exige un valor
logdir=${1:-/var/log}
src=${1:?Usage: backup.sh SOURCE [DEST]}

La primera forma usa /var/log cuando el primer parámetro falta o está vacío. La segunda detiene un guion no interactivo en cualquiera de los dos casos y muestra su mensaje en la salida de error estándar. Los dos puntos forman parte de ambas formas. Un valor predeterminado se usa para esta expansión; ${1:-...} no añade un argumento a la lista de parámetros posicionales.

Registra un fallo parcial

Un guion que cuenta líneas en archivos puede continuar después de una entrada incorrecta y aun así comunicar que la tarea completa quedó incompleta:

#!/bin/bash
if [ "$#" -eq 0 ]; then
  echo "Usage: $0 FILE..." >&2
  exit 2
fi
status=0
for f in "$@"; do
  if [ -f "$f" ]; then
    if lines=$(wc -l < "$f"); then
      echo "$f: $lines lines"
    else
      echo "$f: could not count lines" >&2
      status=1
    fi
  else
    echo "$f: not a regular file" >&2
    status=1
  fi
done
exit "$status"

Para notes.txt missing.txt, el guion muestra el recuento del archivo legible e informa del archivo ausente y después termina con 1. La asignación se comprueba directamente, por lo que un fallo de lectura no se convierte en un recuento vacío considerado correcto. Un éxito posterior nunca restablece a 0 el indicador de fallo almacenado.

Gestiona opciones sencillas antes de los nombres de archivo
verbose=0
while [ "$#" -gt 0 ]; do
  case "$1" in
    -v) verbose=1; shift ;;
    -h) echo "Usage: $0 [-v] FILE..."; exit 0 ;;
    --) shift; break ;;
    -*) echo "Unknown option: $1" >&2; exit 2 ;;
    *) break ;;
  esac
done

Cada opción reconocida se procesa y elimina con shift. El primer argumento ordinario termina el análisis de opciones; -- también lo termina y se elimina. El "$@" restante contiene los nombres de archivo, incluido un nombre que empiece por - después de --. getopts de Bash admite un análisis más completo de opciones cortas.

Un guion sin supervisión necesita obtener todas las entradas obligatorias de argumentos, valores predeterminados o configuración. read puede quedar bloqueado esperando un terminal o fallar inmediatamente al llegar al fin de archivo. Sustituir un argumento ausente por una indicación dejaría a una tarea programada sin una forma fiable de continuar.

Puntos clave

  • Valida el número antes de expandir los argumentos obligatorios.
  • Un mensaje de uso nombra las entradas obligatorias, opcionales y repetibles.
  • ${1:-value} proporciona un valor predeterminado; ${1:?message} rechaza un valor ausente o vacío.
  • Comprueba el resultado de la operación incluso después de comprobar el tipo de archivo de entrada.
  • Conserva un estado de fallo general cuando continúes procesando varias entradas.
  • Procesa las opciones con shift y respeta -- como final de las opciones.
6

Programa la ejecución automática de guiones

Un guion sin supervisión necesita una programación y una forma de inspeccionar sus resultados. Cron expresa las horas coincidentes en una línea; systemd asocia un servicio con un temporizador. Leerás ambas formas, proporcionarás el entorno que necesita la tarea y mantendrás disponible su salida. Comprobar por separado la próxima activación y el resultado de la última tarea ayuda a distinguir una programación activa de un trabajo que realmente tuvo éxito.

6.1 Programa tareas con cron

Cron inicia comandos a las horas que coinciden con la programación. La tabla de cron de cada usuario guarda su programación y las tareas se ejecutan con su identidad. Un guion programado necesita tanto una expresión de tiempo correcta como un entorno que proporcione sus rutas, entradas y destino de salida.

Lee los cinco campos

Usa crontab -e para editar tu tabla y crontab -l para inspeccionarla. crontab -r elimina toda la tabla sin preguntar; usa el editor para eliminar una sola tarea.

Campo, en ordenValores
Minuto0–59
Hora0–23
Día del mes1–31
Mes1–12
Día de la semana0–7; 0 y 7 significan domingo
30 2 * * * /home/sam/bin/backup.sh

Esto se ejecuta todos los días a las 02:30. Los asteriscos aceptan todos los valores de un campo. 0 9 * * 1-5 selecciona las 09:00 de lunes a viernes y 0 0 1 * * selecciona la medianoche del primer día de cada mes. Las horas usan la zona horaria del sistema salvo que la configuración de cron especifique otra zona admitida.

Combina rangos, listas e incrementos

Una coma enumera valores: 1,15 en el campo del día del mes selecciona el primero y el decimoquinto. Un guion indica un rango y / introduce un incremento. */15 en el campo de minutos selecciona 0, 15, 30 y 45.

*/20 8-10 * * * selecciona tres minutos en cada una de tres horas: nueve ejecuciones diarias, que comienzan a las 08:00 y terminan a las 10:40. Los incrementos vuelven a empezar dentro de su campo. */45 se ejecuta en el minuto 0 y el minuto 45 de cada hora; el intervalo hasta el minuto 0 de la hora siguiente es de solo 15 minutos.

Cuando tanto el día del mes como el día de la semana están restringidos, basta con que coincida cualquiera de los dos. 0 12 13 * 5 selecciona el mediodía del día 13 y de los viernes, no solo el viernes 13. Los demás campos también deben coincidir.

Las cadenas especiales sustituyen los cinco campos: @hourly, @daily, @weekly, @monthly, @yearly y @reboot. @daily significa medianoche, mientras que @reboot se ejecuta una vez al arrancar.

Proporciona rutas y conserva la salida

Cron normalmente usa /bin/sh para su línea de comandos, un PATH corto y ningún ajuste de inicio del intérprete de comandos interactivo. La propia línea de intérprete de Bash de un guion ejecutable sigue seleccionando Bash. Usa rutas absolutas para el guion y sus archivos, o establece PATH al principio de la tabla de cron.

30 2 * * * /home/sam/bin/backup.sh >> /home/sam/backup.log 2>&1

La tarea añade ambos flujos de salida al final del registro. Sin redirección, cron envía la salida por correo cuando está configurado, incluso mediante MAILTO; de lo contrario, la salida puede perderse. Un signo de porcentaje tiene una función especial en un comando de crontab: inicia un salto de línea y la entrada posterior. Escapa un formato de fecha en ese contexto, como en date +\%F. Un comando de fecha dentro de un guion separado usa el %F ordinario.

Distingue las programaciones del sistema y las tareas pendientes

/etc/crontab y los archivos de /etc/cron.d/ añaden un campo de usuario después de los cinco campos de tiempo. Por ejemplo, 30 2 * * * root /usr/local/bin/backup.sh se ejecuta como superusuario. No añadas ese campo de usuario a una tabla de cron personal.

Muchas distribuciones también ejecutan los archivos ejecutables que cumplen los requisitos en /etc/cron.daily/, /etc/cron.weekly/ y /etc/cron.monthly/. Las reglas predeterminadas de nombres de run-parts en Debian omiten los nombres que contienen puntos, así que usa allí backup-notes, no backup-notes.sh. Cron pierde las ejecuciones cuya hora pasa mientras el equipo está apagado. Anacron puede ejecutar tareas periódicas diarias, semanales o mensuales pendientes después del arranque.

Puntos clave

  • Una tabla de cron personal tiene cinco campos de tiempo seguidos directamente de un comando.
  • Las listas, los rangos y los incrementos seleccionan valores dentro de cada campo.
  • Si los campos de día del mes y día de la semana están restringidos, basta con que coincida cualquiera de los dos.
  • Usa rutas absolutas y un registro de salida para tareas sin supervisión.
  • Escapa % en un comando de crontab, incluidos los formatos de fecha.
  • Las tablas de cron del sistema añaden un campo de usuario; los directorios periódicos también aplican reglas para admitir archivos.
  • Cron pierde las ejecuciones mientras la máquina está apagada; anacron permite ejecutar tareas periódicas pendientes.

6.2 Programa tareas con temporizadores de systemd

Systemd separa el trabajo de su programación. Una unidad de servicio describe el comando que se debe ejecutar. Una unidad de temporizador describe cuándo iniciarlo. De forma predeterminada, backup.timer activa backup.service, usando el nombre base compartido para conectar ambos.

Escribe el servicio y la programación de calendario

Coloca estas unidades del sistema en /etc/systemd/system/:

# backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

Type=oneshot es adecuado para un guion que se ejecuta una vez y termina. Usa una ruta absoluta para el comando y haz que el guion sea ejecutable con una línea de intérprete de Bash. El temporizador proporciona la programación:

# backup.timer
[Unit]
Description=Run backup.service daily at 02:30

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target

OnCalendar busca coincidencias con fechas y horas del reloj. Aquí, la fecha con comodines acepta todos los días. Persistent=true permite recuperar tareas pendientes después de que el temporizador haya estado inactivo: si se perdió al menos una ejecución de calendario, inicia el servicio una vez al reactivarse. No repite cada ejecución perdida.

Carga y activa el temporizador
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

Recarga las definiciones después de crear o cambiar archivos de unidad. enable --now inicia el temporizador inmediatamente y lo habilita para futuros arranques. Habilitar solo el servicio no crea una programación. Prueba el trabajo por separado con sudo systemctl start backup.service.

Elige entre hora del reloj y tiempo transcurrido
AjusteProgramación
OnCalendar=Mon..Fri *-*-* 09:00:00De lunes a viernes a las 09:00
OnCalendar=*:0/15Minutos 0, 15, 30 y 45 de cada hora
OnBootSec=10minDiez minutos después del arranque
OnUnitActiveSec=1hUna hora después de la última activación del servicio

Las expresiones de calendario pueden usar daily para la medianoche de cada día o weekly para el lunes a medianoche. Comprueba una expresión con systemd-analyze calendar "Mon..Fri 09:00" para ver su interpretación y su próxima ocurrencia.

Los dos últimos ajustes son temporizadores monotónicos: miden el tiempo transcurrido desde un evento. Combínalos para una primera ejecución después del arranque y activaciones posteriores cada hora. Persistent=true se aplica a los temporizadores de calendario; no añade la recuperación de ejecuciones de calendario a los temporizadores monotónicos.

Inspecciona por separado la programación y los resultados

systemctl list-timers muestra las próximas y las últimas activaciones. systemctl status backup.service muestra el resultado del servicio y journalctl -u backup.service muestra su salida y sus errores. Una próxima ejecución en la lista demuestra que una programación está activa, no que la tarea anterior del guion haya tenido éxito.

Los temporizadores tienen un margen de activación. AccuracySec tiene un valor predeterminado de un minuto; AccuracySec=1s reduce el margen de agrupación. RandomizedDelaySec añade deliberadamente un retraso aleatorio para distribuir el trabajo entre máquinas. Estos ajustes no garantizan un segundo de inicio exacto cuando hay carga.

Ejecuta un temporizador propio de usuario

Los archivos de unidad de usuario se guardan en ~/.config/systemd/user/ y los comandos usan systemctl --user, incluidos daemon-reload, enable --now y list-timers. Un gestor de usuario normalmente se ejecuta con la sesión de ese usuario. Un administrador puede habilitar la persistencia del gestor de usuario sin sesión abierta con loginctl enable-linger username para mantenerlo disponible sin iniciar sesión.

Cron necesita una línea de tiempo compacta y funciona sin systemd. Los temporizadores añaden un resultado de servicio y un registro, recuperación de ejecuciones de calendario y más control. Ninguno carga normalmente ~/.bashrc; ambos necesitan guiones que funcionen con rutas explícitas y sin indicaciones interactivas.

Puntos clave

  • El servicio indica qué ejecutar; el temporizador indica cuándo.
  • Recarga las unidades modificadas y habilita el .timer con --now.
  • Los temporizadores de calendario siguen la hora del reloj; los monotónicos miden el tiempo desde eventos.
  • Persistent=true ejecuta una vez el trabajo de calendario pendiente al reactivarse.
  • Comprueba tanto la próxima activación del temporizador como el estado y el registro del servicio.
  • Los temporizadores de usuario necesitan un gestor de usuario en ejecución, con persistencia habilitada para ejecutarse sin una sesión abierta.

Ejemplos de Guiones de Bash

6 Lecciones Interactivas

1

Guarda un informe de directorio repetible

9 pasos
Crea un pequeño informe de Bash, ejecútalo mediante su ruta y distingue la ejecución como programa de la ejecución en el intérprete actual.
  1. 1
    IntroducciónReúne una tarea repetida en un archivo

    A menudo compruebas dónde estás, listas un directorio y muestras un mensaje de finalización. Guardar los comandos permite repetirlos en el mismo orden.

    Un guion es un archivo de texto sin formato que lee un intérprete. Crearás un pequeño informe, seleccionarás Bash explícitamente y lo ejecutarás en un intérprete de comandos hijo. El nombre, el permiso de ejecución y la ubicación del archivo responden cada uno a una pregunta distinta sobre cómo iniciarlo.

  2. 2
    EjemploEscribe los comandos en orden

    Guarda esto como folder-report.sh en un editor de texto sin formato:

    #!/bin/bash
    pwd
    ls
    echo "Report finished"
    

    La línea de intérprete selecciona Bash cuando el archivo se ejecuta directamente. El comentario explica la tarea, pero no se ejecuta. Después, Bash ejecuta pwd, ls y echo en ese orden. La terminación .sh ayuda a reconocer el archivo; no selecciona el intérprete.

  3. 3
    DesafíoComprueba qué selecciona el lenguaje

    Un colega cambia la primera línea a #!/bin/sh y después añade [[ ... ]]. El archivo sigue terminando en .sh. ¿Por qué puede fallar?

    ---reveal---

    La línea de intérprete selecciona sh, que puede ser dash y no entender [[ ... ]] de Bash. La extensión no elige el lenguaje. Restablece una línea de intérprete de Bash para usar sus funciones, con #! al principio mismo de la primera línea.

  4. 4
    ExplicaciónLee primero el archivo con Bash

    Ejecuta bash folder-report.sh. Esto inicia Bash y le pasa el archivo de guion legible; el guion no necesita permiso de ejecución. El intérprete elegido ya es Bash, por lo que la línea de intérprete no toma esa decisión.

    Deberías ver una ruta, un listado y el mensaje «Report finished». Las rutas relativas usadas por los comandos dentro del guion se resuelven desde su directorio de trabajo, no automáticamente desde el directorio del archivo de guion.

  5. 5
    EjemploPermite la ejecución directa

    Añade permiso de ejecución para el propietario y ejecuta la ruta exacta:

    chmod u+x folder-report.sh
    ./folder-report.sh
    

    ./ indica el directorio actual. La ejecución directa usa la línea de intérprete del archivo. Si el archivo es legible pero no ejecutable, el comando bash anterior puede funcionar mientras este falla con «Permission denied». El permiso y la selección del intérprete son partes separadas del inicio.

  6. 6
    ConsejoEncuentra el guion por su nombre

    Escribir folder-report.sh sin una barra pide a Bash que busque en PATH. El directorio actual normalmente no está en esa lista.

    Un directorio bin personal permite ejecutar el guion desde otros directorios cuando está en PATH. Inspecciona echo "$PATH" y usa command -v folder-report.sh para ver qué ejecutable selecciona ese nombre. Si una copia antigua aparece primero en PATH, editar una copia más nueva en otro lugar no cambiará lo que ejecuta ese nombre.

  7. 7
    DesafíoMantén un cambio de directorio en el intérprete adecuado

    El guion ahora comienza con cd /var/log. Después de que termine ./folder-report.sh, ¿se ha desplazado tu terminal allí? ¿Cómo podría desplazarlo un archivo de configuración?

    ---reveal---

    El guion ejecutado funciona en un intérprete de comandos hijo, por lo que su cambio de directorio no desplaza el terminal padre. Ejecutar un archivo con source ./settings.sh ejecuta sus comandos en el intérprete actual y puede cambiar el directorio de esa sesión. Esta forma de ejecución usa el lenguaje del intérprete actual.

  8. 8
    DesafíoDiagnostica el inicio antes de editar los comandos

    Un informe legible funciona con bash folder-report.sh. La ejecución directa informa «Permission denied» y escribir solo su nombre informa «command not found». ¿Qué dos problemas de inicio debes comprobar?

    ---reveal---

    Comprueba el permiso de ejecución del guion para la ejecución directa. Después comprueba PATH o usa su ruta explícita ./ para localizarlo. Una línea de intérprete de Bash válida selecciona el intérprete, pero no puede conceder permisos ni colocar el archivo en PATH.

  9. 9
    RepasoEl inicio implica varias decisiones separadas

    El archivo contiene la secuencia de comandos. El intérprete lee su lenguaje, los permisos permiten la ejecución directa y PATH o una barra localizan el archivo.

    Un guion ejecutado funciona en un intérprete de comandos hijo. Un archivo de configuración ejecutado con source funciona en el intérprete que ya está abierto, por lo que sus asignaciones y cambios de directorio pueden permanecer en esa sesión.

2

Crea un nombre de informe con fecha sin perder espacios

11 pasos
Sigue los valores mediante la asignación, la protección con comillas, la captura de comandos y los cálculos con números enteros.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónSigue un valor hasta un comando
  2. 2
    EjemploAlmacena un destino de varias palabras
  3. 3
    ConexiónPasa el ajuste a un proceso hijo
  4. 4
    DesafíoSepara un nombre de su sufijo
  5. 5
    EjemploConserva la ruta almacenada
  6. 6
    DesafíoElige entre texto fijo y texto variable
  7. 7
    EjemploCaptura una fecha para el nombre
  8. 8
    EjemploCalcula antes de insertar el valor
  9. 9
    DesafíoLocaliza la fracción perdida
  10. 10
    DesafíoCombina la ruta y el valor capturado
  11. 11
    RepasoDistingue las tres funciones
3

Evita que una búsqueda fallida se convierta en un informe satisfactorio

10 pasos
Inspecciona una cadena de comandos conectados por tuberías, conserva el fallo y elige la comprobación de depuración adecuada.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónTrata el resultado como parte de la tarea
  2. 2
    EjemploDetecta el fallo oculto de un comando anterior
  3. 3
    Idea claveHaz que la cadena de comandos comunique su fallo
  4. 4
    DesafíoGuarda el estado que importa
  5. 5
    EjemploGestiona explícitamente el trabajo fallido
  6. 6
    ExplicaciónElige entre comprobación de sintaxis y trazado de ejecución
  7. 7
    ExplicaciónInterpreta las opciones de error como controles separados
  8. 8
    DesafíoExplica por qué continúa este guion
  9. 9
    DesafíoMantén informado a quien llamó al guion
  10. 10
    RepasoLee tanto los datos como el resultado
4

Inspecciona los archivos entrantes y lee sus registros

15 pasos
Usa pruebas, ramas ordenadas y bucles para procesar archivos sin perder nombres ni líneas.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónDeja que cada tipo de entrada elija su siguiente paso
  2. 2
    EjemploElige una prueba para el tipo de ruta
  3. 3
    ExplicaciónCompara los valores de la forma adecuada
  4. 4
    DesafíoInterpreta una prueba de archivo negada
  5. 5
    EjemploSelecciona una acción con el resultado de un comando
  6. 6
    DesafíoSigue umbrales que se solapan
  7. 7
    ExplicaciónCompara una palabra de acción con case
  8. 8
    EjemploProcesa un archivo por iteración con un patrón
  9. 9
    DesafíoExplica el caso de un directorio vacío
  10. 10
    ConsejoElige un límite numérico variable
  11. 11
    EjemploLee un registro sin dividirlo por sus espacios
  12. 12
    DesafíoConserva el último registro sin salto de línea
  13. 13
    ConexiónEspera sin comprobar continuamente
  14. 14
    DesafíoDiagnostica un total que permanece en cero
  15. 15
    RepasoAjusta la estructura a los datos
5

Acepta archivos de entrada e informa de fallos parciales

10 pasos
Valida un comando reutilizable, procesa una opción y conserva el resultado general.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónHaz que la entrada forme parte de la llamada al comando
  2. 2
    EjemploInspecciona los límites de la llamada
  3. 3
    ExplicaciónProcesa la opción inicial
  4. 4
    DesafíoConserva un argumento vacío en el recuento
  5. 5
    EjemploRechaza una llamada sin archivos de entrada
  6. 6
    ExplicaciónElige un valor predeterminado solo para una entrada opcional
  7. 7
    EjemploComprueba la propia operación de lectura
  8. 8
    DesafíoRecuerda el fallo anterior
  9. 9
    DesafíoDetén el análisis antes de un nombre de archivo con guion
  10. 10
    RepasoDa a los comandos reutilizables un comportamiento fiable
6

Programa un informe y verifica su última ejecución

12 pasos
Lee expresiones de cron, crea un par de servicio y temporizador y distingue la hora programada del éxito de la tarea.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónPrograma solo tareas que tengan toda la entrada necesaria
  2. 2
    EjemploLee una entrada de una tabla de cron personal
  3. 3
    DesafíoSigue un incremento de minutos al cambiar de hora
  4. 4
    ConsejoDa a la tarea un destino de salida
  5. 5
    ConexiónDistingue una ejecución omitida de una fallida
  6. 6
    EjemploPon el trabajo en un servicio
  7. 7
    EjemploPon la hora en el temporizador correspondiente
  8. 8
    ExplicaciónCarga los cambios y habilita la programación
  9. 9
    DesafíoComprueba el resultado además de la próxima hora
  10. 10
    ExplicaciónCuenta el tiempo desde un evento cuando sea necesario
  11. 11
    DesafíoElige cómo recuperar tareas después de una interrupción
  12. 12
    RepasoInspecciona la programación y la tarea por separado

Ejercicios de Guiones de Bash

50 Preguntas de Práctica en 5 sets

Set 1: Sigue valores, registros y programaciones10 Preguntas de Práctica

Pregunta 1 de 10

Un guion ejecutado directamente informa /bin/bash^M: bad interpreter, pero /bin/bash existe. ¿Qué cambio en el archivo resuelve el problema indicado?
  1. Cambiar la extensión del guion de .sh a .bash.
  2. Mover el guion a un directorio incluido en PATH.
  3. Añadir permiso de ejecución para el propietario.
  4. Convertir el guion a finales de línea de Unix.
Mostrar respuestaOcultar respuesta
Respuesta: D
^M indica un retorno de carro de los finales de línea de Windows, que hace que la ruta del intérprete sea distinta de /bin/bash. Convertir el archivo a finales de línea de Unix elimina ese carácter adicional. El permiso de ejecución no puede corregir caracteres dentro de la ruta del intérprete y PATH no resuelve una ruta fija de la línea de intérprete.

Pregunta 2 de 10

¿Cómo asignas el texto «North Hall» a una variable de Bash llamada site?
  1. site="North Hall"
  2. site = "North Hall"
  3. $site="North Hall"
  4. site=North Hall
Mostrar respuestaOcultar respuesta
Respuesta: A
La asignación usa el nombre de la variable sin signo de dólar y no tiene espacios alrededor de =. Las comillas conservan las dos palabras como valor. Con espacios alrededor de =, Bash trata site como un comando; sin comillas alrededor del valor, Hall pasa a ser una palabra de comando en lugar de parte de la asignación.

Pregunta 3 de 10

¿Qué valor asigna left=$(( 29 % 6 ))?
  1. 4
  2. 4.83
  3. 5
  4. 1
Mostrar respuestaOcultar respuesta
Respuesta: C
Cuatro grupos enteros de 6 usan 24 y dejan un resto de 5. El operador % devuelve ese resto. El cociente 4 se obtendría mediante división entera con /, mientras que la aritmética de Bash no produce un cociente decimal como 4,83 a partir de esta expresión.

Pregunta 4 de 10

A un guion le falta el done de cierre. ¿Qué comando puede detectar ese problema de sintaxis sin ejecutar el guion?
  1. bash -x batch.sh
  2. bash -n batch.sh
  3. bash batch.sh
  4. source ./batch.sh
Mostrar respuestaOcultar respuesta
Respuesta: B
bash -n lee el guion y comprueba su estructura sin ejecutar los comandos. Puede detectar un bucle al que le falta el done de cierre. bash -x también lee el guion, pero lo ejecuta con trazado, por lo que los comandos válidos anteriores podrían ejecutarse antes de encontrar el problema de sintaxis.

Pregunta 5 de 10

¿Cuáles son los resultados de [ 06 = 6 ] y [ 06 -eq 6 ], en ese orden?
  1. Verdadero y después falso.
  2. Verdadero y después verdadero.
  3. Falso y después verdadero.
  4. Falso y después falso.
Mostrar respuestaOcultar respuesta
Respuesta: C
La primera prueba compara texto y «06» contiene un cero inicial que no aparece en «6», por lo que es falsa. La segunda compara valores enteros y tiene éxito porque ambos representan seis. Tratar ambas pruebas como comparaciones numéricas pasaría por alto el propósito de los distintos operadores.

Pregunta 6 de 10

Un directorio contiene a.csv y late batch.csv, ambos archivos regulares. ¿Qué valores se usan en for f in *.csv; do echo "$f"; done?
  1. Dos elementos: a.csv y late batch.csv.
  2. Tres elementos: a.csv, late y batch.csv.
  3. Un elemento: el patrón literal *.csv.
  4. Un elemento: a.csv late batch.csv.
Mostrar respuestaOcultar respuesta
Respuesta: A
El patrón se expande a nombres de archivo coincidentes como elementos separados e intactos, por lo que el bucle recibe dos nombres. El espacio dentro de «late batch.csv» no divide un nombre producido por la expansión del patrón. Proteger "$f" con comillas en el cuerpo mantiene unido ese valor cuando se pasa a otro comando.

Pregunta 7 de 10

Un archivo contiene oak, un salto de línea y después elm sin salto de línea final. ¿Qué recuento se muestra?

count=0
while IFS= read -r line; do
  count=$(( count + 1 ))
done < trees.txt
echo "$count"
  1. 0
  2. 2
  3. 3
  4. 1
Mostrar respuestaOcultar respuesta
Respuesta: D
La primera lectura obtiene un registro terminado en salto de línea y entra en el cuerpo, aumentando el recuento a 1. La segunda almacena «elm», pero devuelve un fallo al llegar al fin de archivo, por lo que se omite el cuerpo. La redirección de entrada conserva el recuento actualizado; añadir || [ -n "$line" ] también procesaría el último registro y produciría 2.

Pregunta 8 de 10

Después de la llamada ./task.sh -v "blue room" output.txt, el guion ejecuta shift. ¿Cuáles son ahora los valores de $1 y $#?
  1. -v y 2.
  2. blue room y 2.
  3. blue y 3.
  4. output.txt y 1.
Mostrar respuestaOcultar respuesta
Respuesta: B
shift procesa el primer argumento, «-v», y desplaza los dos argumentos restantes. El nombre entre comillas pasa a ser $1 y $# baja de 3 a 2. El espacio dentro del nombre permanece intacto; el desplazamiento no divide el texto ni elimina también el segundo argumento.

Pregunta 9 de 10

¿Cuántas veces al día se ejecuta */25 10-12 * * * y cuándo es su última ejecución?
  1. 6 veces; la última a las 12:25.
  2. 8 veces; la última a las 12:55.
  3. 9 veces; la última a las 12:50.
  4. 9 veces; la última a las 13:00.
Mostrar respuestaOcultar respuesta
Respuesta: C
El campo de minutos selecciona 0, 25 y 50, y el rango de horas incluye 10, 11 y 12. Tres minutos seleccionados en cada una de tres horas dan nueve ejecuciones, que terminan a las 12:50. Un recuento continuo de 25 minutos entre horas sería incorrecto porque el incremento vuelve a empezar dentro de cada hora.

Pregunta 10 de 10

Con la asociación predeterminada de unidades, ¿qué servicio activa inventory.timer?
  1. inventory.service
  2. timer.service
  3. inventory.timer.service
  4. inventory.target
Mostrar respuestaOcultar respuesta
Respuesta: A
Un temporizador normalmente activa el servicio con el mismo nombre base, por lo que inventory.timer inicia inventory.service. El temporizador almacena la programación, mientras que el servicio define el trabajo. Añadir otra extensión al nombre completo del temporizador no identificaría la unidad correspondiente de forma predeterminada.
Set 2: Sigue los datos a través de un guion completo10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Un terminal de Bash comienza con zone=west. El archivo settings.sh contiene solo zone=east. El terminal ejecuta bash settings.sh, después source ./settings.sh y luego bash -c 'echo "${zone:-unset}"'. La variable nunca se exportó. ¿Qué muestra el último comando?
  1. east
  2. unset
  3. west
  4. Una línea vacía.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Con name=archive, ¿qué muestra echo "${name}_ready"?
  1. name_ready
  2. archive
  3. Una línea vacía.
  4. archive_ready
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un guion almacena completed=18 y total=32. ¿Qué resultado entero produce $(( completed * 100 / total ))?
  1. 56
  2. 0
  3. 57
  4. 56.25
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

El archivo absent.log no existe. ¿Qué estado de salida recibe quien llamó al guion?

#!/bin/bash
set -o pipefail
grep NOTICE absent.log | wc -l
status=$?
echo "Count ended"
exit "$status"
  1. 0
  2. 1
  3. 2
  4. 127
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

¿Qué muestra este guion?

set -e
false || echo "Handled"
echo "Next"
  1. Solo Handled.
  2. Solo Next.
  3. Handled y después Next.
  4. No muestra nada.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

En un bloque case, ¿por qué debe ir *) después de los patrones de acciones con nombre?
  1. Coincide con cualquier valor y ocultaría las ramas posteriores.
  2. No coincide con ningún valor hasta que falle un patrón con nombre.
  3. Repite la rama anterior para los valores sin coincidencia.
  4. Se aplica solo a nombres de archivo del directorio actual.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

El directorio actual contiene solo los archivos regulares draft one.jpeg, final.jpeg y notes.txt. ¿Cuál es la salida?

count=0
for f in *.jpeg; do
  [ "$f" = final.jpeg ] && continue
  echo "${f%.jpeg}.jpg"
  count=$(( count + 1 ))
done
echo "$count"
  1. draft.jpg, después one.jpg y después 2.
  2. draft one.jpg, después final.jpg y después 2.
  3. draft one.jpeg.jpg y después 1.
  4. draft one.jpg y después 1.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un guion ejecuta until [ -f /tmp/upload.ready ]; do sleep 3; done. El archivo regular ya existe antes de que comience el bucle. ¿Cuántas veces se ejecuta el cuerpo?
  1. Exactamente una vez.
  2. Cero veces.
  3. Indefinidamente.
  4. Hasta que se elimine.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un guion de procesamiento por lotes comienza con status=0. Una entrada incorrecta establece status=1 y una entrada posterior tiene éxito. ¿Qué final indica que la solicitud quedó incompleta?
  1. Establecer status=0 tras el éxito y usar exit "$status".
  2. Mantener status=1 y terminar con un echo satisfactorio.
  3. Establecer status=0 y mostrar un error en la salida estándar.
  4. Mantener status=1 y usar exit "$status".
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Se han escrito archivos nuevos de temporizador y servicio del sistema. ¿Qué comando hace que systemd vuelva a leer sus definiciones antes de habilitar el temporizador?
  1. sudo systemctl daemon-reload
  2. sudo systemctl start report.service
  3. sudo systemctl list-timers
  4. sudo journalctl -u report.service
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 3: Lee y ejecuta pequeños guiones de Bash10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Un guion usa la sintaxis [[ ... ]] de Bash, pero su primera línea es #!/bin/sh. En esta máquina, sh es dash. ¿Qué primera línea selecciona el intérprete deseado?
  1. #!/bin/sh bash
  2. # /bin/bash
  3. #!/bin/bash
  4. #!/usr/bin/env sh
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

El propietario puede leer un guion, pero este no tiene permiso de ejecución. ¿Cómo puede el propietario ejecutar sus comandos de Bash sin cambiar ese permiso?
  1. ./audit.sh
  2. bash audit.sh
  3. chmod u-x audit.sh
  4. source bash audit.sh
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Con label="west side", ¿qué argumentos formatea printf '<%s>\n' "$label"?
  1. Un argumento: west side.
  2. Dos argumentos: west y side.
  3. Un argumento: el literal $label.
  4. Un argumento: el literal "west side".
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un guion establece file="shift notes.txt". ¿Cómo debe copiar ese único archivo al directorio existente saved?
  1. cp '$file' saved/
  2. cp $file saved/
  3. cp "file" saved/
  4. cp "$file" saved/
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Un comando acaba de fallar con el estado 7. ¿Qué asignación conserva inmediatamente ese resultado para usarlo después?
  1. result=$#
  2. result=$?
  3. result=$!
  4. result=0
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

La ruta archive existe y es un directorio. ¿Cuáles son los resultados de [ -f archive ] y [ -d archive ], en ese orden?
  1. Verdadero y después verdadero.
  2. Verdadero y después falso.
  3. Falso y después verdadero.
  4. Falso y después falso.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

¿Qué muestra este código?

used=14
limit=20
percent=$(( used * 100 / limit ))
if [ "$percent" -ge 60 ]; then
  used=$(( used + 2 ))
elif [ "$percent" -ge 70 ]; then
  used=$(( used + 5 ))
fi
echo "$used"
  1. 16
  2. 19
  3. 21
  4. 14
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un guion se llama con ./label.sh "East Wing" report.txt. ¿Cuáles son los valores de $# y $2?
  1. 3 y Wing.
  2. 2 y East Wing.
  3. 3 y report.txt.
  4. 2 y report.txt.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un guion no interactivo de Bash usa dir=${1:-/srv/logs}. Se llama con un argumento que es una cadena vacía entre comillas. ¿Qué valor se asigna?
  1. Una cadena vacía.
  2. El texto literal ${1}.
  3. /srv/logs
  4. El guion termina con un error.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

En una tabla de cron personal, ¿qué programación especifica 25 4 * * * /home/rae/bin/audit.sh?
  1. Todos los días a las 04:25.
  2. Todos los días a las 25:04.
  3. Cada hora en el minuto 4.
  4. El día 4 a las 00:25.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 4: Diagnostica entradas, flujo de control y periodos de inactividad10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Se cambia el nombre de un archivo de guion de weekly.sh a weekly, sin modificar su contenido ni sus permisos. ¿Qué efecto tiene perder la extensión en la elección del intérprete que hace Linux según la línea de intérprete?
  1. Hace que Linux elija el intérprete de inicio de sesión actual.
  2. Hace que Linux elija /bin/sh de forma predeterminada.
  3. Deja sin cambios la elección del intérprete.
  4. Impide que Linux lea la línea de intérprete.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Un proceso padre de Bash ejecuta export REGION=north y después inicia un guion que asigna REGION=south y termina. ¿Qué valor permanece en el proceso padre?
  1. north
  2. south
  3. Un valor vacío.
  4. La variable deja de estar establecida.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

En un directorio que por lo demás está vacío, un guion establece pattern="*.txt". ¿Qué argumento recibe touch "$pattern"?
  1. Ninguna ruta, porque nada coincide.
  2. Una ruta por cada archivo de texto existente.
  3. La ruta literal "*.txt", con comillas.
  4. La ruta literal *.txt.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

¿Qué ocurre en este guion no interactivo?

set -eu
dest=
if [ -z "$dest" ]; then
  dest=${2:-/srv/archive}
fi
echo "$dest"

El guion recibe un solo argumento, input.txt.

  1. Se detiene porque a dest se le asignó texto vacío.
  2. Muestra /srv/archive y termina correctamente.
  3. Se detiene porque falta el segundo argumento.
  4. Muestra input.txt y termina correctamente.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

La variable count contiene 10 y se puede escribir en el directorio actual, donde no hay ningún archivo llamado 4. ¿Qué ocurre?

if [ "$count" > 4 ]; then
  echo "High"
else
  echo "Low"
fi
  1. No crea ningún archivo y muestra High.
  2. Crea 4 y muestra Low.
  3. No crea ningún archivo y muestra Low.
  4. Crea 4 y muestra High.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Un guion compara con case "$value" in [0-9]*) echo "Match" ;; *) echo "No" ;; esac. ¿Qué ocurre para value=8draft?
  1. Muestra Match.
  2. Muestra No.
  3. Falla porque el valor contiene letras.
  4. Muestra tanto Match como No.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

¿Qué se muestra?

i=0
total=0
while [ "$i" -lt 4 ]; do
  i=$(( i + 1 ))
  [ "$i" -eq 2 ] && continue
  total=$(( total + i ))
  [ "$total" -gt 5 ] && break
done
echo "$i:$total"
  1. 4:10
  2. 3:4
  3. 4:8
  4. 2:1
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un guion recibe -v, una cadena vacía entre comillas y "red room", en ese orden. Ejecuta shift y después for arg in "$@"; do echo "<$arg>"; done. ¿Qué se muestra?
  1. <red> y después <room>.
  2. <> y después <red room>.
  3. Solo <red room>.
  4. <-v>, después <> y después <red room>.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

¿Qué fechas selecciona 0 11 9 * 2 /home/rae/bin/check.sh en el cron ordinario?
  1. Solo los martes que son día 9, a las 11:00.
  2. Todos los martes y todos los días 9, a las 11:00.
  3. Todos los martes de septiembre, a las 11:00.
  4. Solo el segundo martes, a las 11:09.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un temporizador de calendario habilitado tiene Persistent=true. Pasan tres activaciones diarias mientras el equipo está apagado. ¿Qué recuperación organiza al reactivarse?
  1. Una activación del servicio para el trabajo de calendario pendiente.
  2. Tres activaciones, una por cada ejecución diaria omitida.
  3. Ninguna activación hasta la próxima coincidencia de calendario.
  4. Activaciones continuas hasta que se apague la máquina.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 5: Combina la protección mediante comillas, las comprobaciones de fallos y las entradas reutilizables10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Un terminal de Bash está en /home/rae, con PATH /home/rae/bin:/usr/local/bin:/usr/bin:/bin. Existen guiones ejecutables de Bash llamados scan en ambos directorios bin y en el directorio actual. Cada uno contiene solo una línea de intérprete de Bash y cd /srv/cache; ese directorio existe y es accesible. ¿Qué archivo ejecuta el primer comando y qué rutas se muestran?

scan
pwd
source ./scan
pwd
  1. /usr/local/bin/scan; después /home/rae y /srv/cache.
  2. /home/rae/bin/scan; después /home/rae y /srv/cache.
  3. ./scan; después /srv/cache y /srv/cache.
  4. /home/rae/bin/scan; después /srv/cache y /srv/cache.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Un directorio contiene solo a.txt y b.txt. Con la configuración predeterminada de división y expansión de nombres de archivo de Bash, ¿cuántos argumentos de datos formatea printf '<%s>\n' $value después de value="*.txt spare"?
  1. Uno: el literal *.txt spare.
  2. Dos: el literal *.txt y spare.
  3. Tres: a.txt, b.txt, spare.
  4. Dos: a.txt spare y b.txt spare.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un comando muestra ready en la salida estándar y warning en la salida de error estándar y después termina correctamente. ¿Qué almacena message=$(the_command)?
  1. Solo ready.
  2. Solo warning.
  3. Ambas líneas en orden.
  4. El estado 0 del comando.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

¿Qué estado de salida recibe quien llamó al guion?

#!/bin/bash
false
saved=$?
true && echo "Handled"
exit $(( saved + 2 ))
  1. 0
  2. 1
  3. 2
  4. 3
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Un guion usa set -u y ya ha asignado folder="". Debe detenerse con un mensaje de diagnóstico útil antes de usar un directorio ausente o vacío. ¿Qué expansión proporciona esa comprobación?
  1. ${folder:?Folder required}
  2. ${folder:-Folder required}
  3. "$folder"
  4. ${folder}
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

¿Qué prueba comprueba si "$text" tiene una longitud distinta de cero?
  1. [ -z "$text" ]
  2. [ -s "$text" ]
  3. [ -n "$text" ]
  4. [ -e "$text" ]
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Para limit=3, ¿qué valores muestra for i in {1..$limit}; do echo "$i"; done con la expansión ordinaria de Bash?
  1. Tres valores: 1, 2, 3.
  2. Un valor: el literal {1..$limit}.
  3. Ningún valor, porque la lista está vacía.
  4. Un valor: el literal {1..3}.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

¿Qué recuento se muestra con el comportamiento predeterminado de las cadenas conectadas por tuberías en Bash? El archivo contiene tres líneas terminadas en salto de línea.

count=5
cat tasks.txt | while IFS= read -r line; do
  count=$(( count + 1 ))
done
count=$(( count + 2 ))
echo "$count"
  1. 10
  2. 7
  3. 8
  4. 5
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un guion analiza sus entradas con este código y después requiere exactamente dos argumentos de archivo. Tras la llamada ./copy.sh -v -- "early notes.txt" -final.txt, ¿cuántos argumentos quedan y qué debe ocurrir a continuación?

while [ "$#" -gt 0 ]; do
  case "$1" in
    -v) verbose=1; shift ;;
    --) shift; break ;;
    -*) echo "Unknown option" >&2; exit 2 ;;
    *) break ;;
  esac
done
  1. Quedan tres; se rechaza el marcador adicional de fin de opciones.
  2. Quedan dos; se rechaza -final.txt como opción desconocida.
  3. Quedan dos; se validan ambas rutas y se intenta la copia.
  4. Queda uno; se usa un valor predeterminado para el destino ausente.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un guion programado usa sintaxis de Bash y es ejecutable con una línea de intérprete de Bash. Funciona en el terminal, pero cron informa de que falta un comando auxiliar. El comando auxiliar existe en /home/rae/.local/bin. ¿Qué cambio resuelve la diferencia probable?
  1. Cambiar la línea de intérprete de Bash del guion a /bin/sh.
  2. Añadir un campo de nombre de usuario a la tabla de cron personal.
  3. Hacer ejecutable por segunda vez el guion que ya lo es.
  4. Usar la ruta absoluta del comando auxiliar o establecer PATH para cron.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

¿Te atascas con una pregunta tuya? Ayuda con Tareas

Términos Clave

76 Términos Clave, cada uno con su definición

A

Anacron
Anacron ejecuta tareas periódicas omitidas durante una interrupción, normalmente ocupándose del trabajo diario, semanal y mensual después del arranque.
Anacron puede ejecutar una tarea diaria pendiente en un portátil que estaba apagado a su hora programada habitual.
Asignación
Una asignación almacena un valor bajo un nombre de variable mediante name=value, sin espacios alrededor del signo igual.
La asignación name="Lee Kim" mantiene las dos palabras juntas como un valor almacenado.

B

Bash
Bash es Bourne Again Shell, un intérprete de comandos usado de forma interactiva y para ejecutar guiones en sistemas Linux.
Un guion que usa [[ ... ]] selecciona Bash en su línea de intérprete para que se entienda su sintaxis condicional.
break
El comando break sale inmediatamente del bucle actual para que la ejecución continúe después del comando que cierra ese bucle.
Un bucle de menú usa break cuando el usuario introduce «q» y ya no deben leerse más opciones del menú.
Bucle for o ciclo for
Un bucle for repite comandos para cada elemento de una lista y asigna ese elemento a su variable de bucle antes de ejecutar el cuerpo.
Un bucle for sobre web1 web2 db1 ejecuta su cuerpo una vez por cada uno de los tres nombres de equipo.
Bucle until
Un bucle until comprueba un comando antes de cada iteración y repite su cuerpo hasta que ese comando tenga éxito.
Un bucle until puede hacer pausas entre comprobaciones mientras espera a que aparezca un archivo que indique que la exportación ha terminado.
Bucle while
Un bucle while comprueba un comando antes de cada iteración y repite su cuerpo mientras ese comando tenga éxito.
Un bucle while que lee un archivo termina cuando read llega al fin de archivo e informa de un fallo.

C

case
Un bloque case compara un valor con patrones en orden y ejecuta los comandos de la primera rama coincidente.
Un bloque case puede gestionar «start», «stop» y un comando sin coincidencia mediante ramas separadas.
Comentario
Un comentario es texto explicativo que el intérprete de comandos ignora y que se introduce con # al principio de una palabra fuera del texto protegido por comillas.
El comentario # Keep a copy for recovery explica por qué se necesita la siguiente copia de archivo.
Comillas dobles
Las comillas dobles conservan los espacios y caracteres comodín de un valor y permiten la expansión de variables, comandos y operaciones aritméticas.
Las comillas dobles en echo "Home: $HOME *" permiten expandir la ruta del directorio personal y conservan el asterisco.
Comillas simples
Las comillas simples encierran texto literal e impiden las expansiones de variables, comandos y comodines dentro de la parte entre comillas.
Las comillas simples hacen que echo '$HOME' muestre los caracteres «$HOME» en lugar de una ruta de directorio personal.
Comparación de cadenas
Una comparación de cadenas comprueba el texto carácter por carácter, por lo que una escritura distinta o ceros iniciales pueden hacer que los valores sean diferentes.
Una comparación de cadenas trata «07» y «7» como distintos, aunque representen el mismo número entero.
Comparación numérica
Una comparación numérica evalúa valores enteros con operadores como -eq y -gt, independientemente de la longitud de su texto.
La comparación numérica [ "$count" -ge 8 ] tiene éxito para un recuento almacenado de 12.
Comprobación de sintaxis
Una comprobación de sintaxis lee un guion para encontrar estructuras incorrectas del intérprete de comandos sin ejecutar los comandos ni comprobar sus resultados reales.
Una comprobación de sintaxis con bash -n detecta la ausencia de done antes de que el bucle pueda ejecutar comandos.
Contador
Un contador es un número almacenado que se actualiza cuando ocurren eventos o iteraciones de un bucle, normalmente sumando uno a su valor anterior.
Un contador inicializado con count=0 puede aumentar una vez por cada línea que lee un bucle.
continue
El comando continue omite los comandos restantes de la iteración actual de un bucle y pasa a la siguiente iteración o comprobación de condición.
Un bucle de archivos usa continue después de que falle una comprobación para que su comando de procesamiento nunca reciba una ruta inexistente.
cron
cron es un servicio de programación en segundo plano que inicia comandos cuando sus campos de tiempo de crontab coinciden con la hora actual.
Una tarea de cron puede ejecutar un guion de informe ejecutable a las 06:15 de lunes a viernes sin tener un terminal abierto.

D

División en palabras
La división en palabras divide una expansión sin comillas en palabras separadas mediante caracteres separadores, normalmente espacios, tabulaciones y saltos de línea.
La división en palabras convierte un valor «my report.txt» sin comillas en dos argumentos antes de que se ejecute cp.
División entera
La división entera calcula un cociente entero y descarta la parte fraccionaria en lugar de producir un resultado decimal.
La división entera hace que $(( 7 / 2 )) produzca 3 aunque el cociente exacto sea 3,5.

E

Ejecución de un archivo en el intérprete actual
La ejecución de un archivo en el intérprete actual consiste en leer sus comandos en el intérprete de comandos actual para que sus asignaciones y cambios de directorio afecten a ese intérprete.
Ejecutar ./settings.sh mediante source carga sus asignaciones de variables directamente en la sesión abierta de Bash.
Ejecución en cortocircuito
La ejecución en cortocircuito usa el estado de un comando para decidir si se ejecuta el siguiente comando de una lista && o ||.
La ejecución en cortocircuito en cd /data || exit 1 detiene los comandos dependientes después de un cambio de directorio fallido.
elif
La palabra clave elif introduce otra condición en un bloque if, que solo se comprueba cuando han fallado todas las condiciones anteriores de ese bloque.
Una prueba elif para un uso del 75 % solo se ejecuta después de que haya fallado la prueba anterior para al menos un 90 %.
Eliminación de sufijos
La eliminación de sufijos es una expansión de parámetros que elimina una terminación coincidente del valor de una variable, como en ${f%.jpeg}.
La eliminación de sufijos convierte «lake.jpeg» en «lake», de modo que un comando de cambio de nombre pueda añadir después «.jpg».
Entorno mínimo
Un entorno mínimo proporciona solo un pequeño conjunto de ajustes de proceso, sin las variables ni los archivos de inicio de una sesión interactiva.
El entorno mínimo de cron puede omitir un directorio bin personal que estaba disponible en el terminal.
errexit
errexit es la opción set -e de Bash, que termina el guion ante fallos no tratados y permite determinadas situaciones en las que se comprueba el estado de un comando.
La opción errexit permite que una condición if fallida seleccione su rama else en lugar de terminar el guion.
Estado de salida
Un estado de salida es un resultado entero de un comando entre 0 y 255; cero significa éxito y los demás valores comunican resultados documentados.
El estado de salida de grep -q distingue entre una coincidencia, la ausencia de coincidencias y un problema al leer la entrada.
Estado de salida de una cadena de comandos
El estado de salida de una cadena de comandos es el resultado de una cadena conectada por tuberías, tomado normalmente de su último comando salvo que pipefail cambie esa regla.
El estado de salida de la cadena puede ser cero cuando grep falla, pero el wc siguiente cuenta correctamente una entrada vacía.
exit
El comando integrado exit termina el intérprete de comandos o el guion y comunica un estado proporcionado, o el estado del comando anterior cuando no se indica ningún número.
Un guion usa exit 2 después de un error de uso para que quien lo llamó reciba un resultado de fallo.
Expansión aritmética
La expansión aritmética evalúa una expresión entera dentro de $(( ... )) e inserta el valor calculado en el comando.
La expansión aritmética convierte "$(( count + 1 ))" en el siguiente recuento entero.
Expansión de llaves
La expansión de llaves crea una lista fija a partir de una notación como {1..5} antes de que Bash realice la expansión de variables en el comando.
La expansión de llaves no puede convertir {1..$n} en un rango basado en el valor almacenado en n.
Expansión de nombres de archivo
La expansión de nombres de archivo sustituye un patrón de nombres de archivo sin comillas por rutas coincidentes; Bash normalmente conserva como texto literal un patrón sin coincidencias.
La expansión de nombres de archivo expande *.log en nombres de archivo coincidentes separados antes de que comience un bucle for.
Expansión de variables
La expansión de variables sustituye un nombre precedido de un signo de dólar por su valor almacenado mientras Bash prepara un comando para ejecutarlo.
La expansión de variables convierte "${file}_old" en «report_old» cuando file contiene «report».
Exportación
Una exportación marca una variable del intérprete de comandos para incluirla en el entorno que heredan los programas que ese intérprete inicia después.
Una exportación de BACKUP_DIR permite que un guion de copia de seguridad recién iniciado lea el destino configurado.

F

Fin de archivo
El fin de archivo es el punto en el que un flujo de entrada no tiene más datos; read de Bash informa de un fallo cuando encuentra esta condición.
Al llegar al fin de archivo, puede almacenarse un registro final sin salto de línea aunque read informe de un fallo.
Final de línea
Un final de línea marca el final de una línea de texto; Unix usa un salto de línea, mientras que Windows suele añadir antes un retorno de carro.
Un final de línea de Windows en una línea de intérprete puede hacer que Linux busque una ruta de intérprete terminada en ^M.

G

Guion del intérprete de comandos
Un guion del intérprete de comandos es un archivo de texto sin formato con comandos del intérprete, guardado para que este los ejecute como una tarea repetible.
Un guion del intérprete de comandos puede crear un directorio de copia de seguridad, copiar notas en él y listar la copia guardada.

I

IFS
IFS es la variable de separadores internos de campos del intérprete de comandos; establecerla vacía para read conserva los espacios en blanco iniciales y finales.
Usar IFS= read -r line conserva los espacios de los extremos de cada registro leído del archivo de entrada.
Incremento de un campo de cron
Un incremento de un campo de cron selecciona valores espaciados regularmente dentro de un campo de tiempo y vuelve a empezar según el rango de ese campo en lugar de medir el tiempo transcurrido.
Un incremento de */45 en los minutos de cron selecciona 0 y 45, y después vuelve a empezar en 0 en la hora siguiente.
Indicador de fallo
Un indicador de fallo es un valor almacenado que recuerda una parte fallida de una tarea mayor para que el estado final siga siendo distinto de cero.
Un indicador de fallo permanece establecido después de un archivo ausente, incluso cuando el guion cuenta correctamente un archivo posterior.
Intérprete
Un intérprete es un programa que lee y ejecuta instrucciones escritas en el lenguaje que entiende.
El intérprete seleccionado por #!/usr/bin/python3 lee código Python en lugar de comandos de Bash.
Iteración
Una iteración es una pasada por el cuerpo de un bucle, que usa el elemento actual de la lista o los valores actuales antes de que comience la siguiente pasada.
Una iteración de un bucle de archivos procesa el único nombre «beach day.jpeg» antes de continuar.

L

Línea de intérprete
Una línea de intérprete es la primera línea, que comienza con #! e indica el intérprete que Linux debe usar para ejecutar un guion.
La línea de intérprete #!/bin/bash comienza en el primer carácter, antes de cualquier comentario o línea en blanco.

M

Manejador de señales y eventos
Un manejador de señales y eventos registra un comando para ejecutarlo cuando ocurre una señal o evento seleccionado del intérprete de comandos, como EXIT cuando termina el proceso de Bash.
Un manejador EXIT puede eliminar el archivo temporal cuya ruta se almacenó antes en el guion.
Mensaje de uso
Un mensaje de uso muestra cómo llamar a un comando, nombra los argumentos obligatorios y marca las entradas opcionales o repetibles.
El mensaje de uso «Usage: count.sh FILE...» indica que las entradas de archivo pueden repetirse.

N

Negación
La negación invierte el éxito y el fallo de un comando o prueba, lo que permite que una condición seleccione los casos en que la condición original es falsa.
La negación en [ ! -d "$p" ] acepta tanto un archivo regular como una ruta que no existe.
nounset
nounset es la opción set -u de Bash, que trata la expansión de una variable no establecida como un error en un guion no interactivo.
Con nounset habilitado, un nombre de variable mal escrito puede detener un guion antes de que use una ruta vacía.
Número de argumentos
El número de argumentos es la cantidad de argumentos posicionales proporcionados, disponible como $#, sin incluir el nombre de invocación.
El número de argumentos es 2 para ./greet.sh Ana "Lee Kim" porque el nombre entre comillas es un argumento.

O

Opción
Una opción es una entrada de la línea de comandos que cambia el comportamiento, a menudo escrita con un guion inicial y procesada antes de los argumentos ordinarios.
La opción -v puede habilitar mensajes adicionales antes de que el guion procese los nombres de archivo restantes.

P

Palabra clave condicional
Una palabra clave condicional como [[ de Bash inicia una estructura de prueba del intérprete de comandos con sus propias reglas de análisis y búsqueda de coincidencias con patrones.
La palabra clave condicional [[ permite usar [[ $name == *.log ]] sin dividir el nombre en palabras.
Parámetro posicional
Un parámetro posicional contiene un argumento proporcionado a un guion, numerado a partir de $1; las posiciones posteriores a la novena requieren llaves.
El parámetro posicional ${10} recupera el décimo argumento sin añadir un cero a $1.
Paso de argumentos a otro comando
El paso de argumentos a otro comando transmite los valores recibidos por un guion a otro comando, normalmente usando "$@" para conservar cada límite.
El paso de argumentos con "$@" mantiene una entrada vacía y un nombre de varias palabras como argumentos separados.
PATH
PATH es el valor de entorno, separado por dos puntos, que enumera los directorios en los que se buscan nombres de comandos que no contienen una barra.
El intérprete de comandos busca job.sh en PATH, pero sigue la ruta explícita del directorio actual en ./job.sh.
Patrón de coincidencia universal
Un patrón de coincidencia universal es un patrón que coincide con todos los valores restantes, normalmente * al final de un bloque case de Bash.
El patrón de coincidencia universal *) informa de comandos desconocidos después de comprobar los subcomandos con nombre.
Permiso de ejecución
El permiso de ejecución permite que un usuario autorizado inicie un archivo como programa, incluido un guion cuya línea de intérprete selecciona su intérprete.
Añadir permiso de ejecución con chmod u+x job.sh permite que el propietario intente ejecutar ./job.sh.
Persistencia del gestor de usuario sin sesión abierta
La persistencia del gestor de usuario sin sesión abierta permite que el gestor de systemd de un usuario permanezca disponible sin una sesión activa para que puedan ejecutarse los servicios y temporizadores de usuario.
Un administrador habilita la persistencia del gestor de usuario cuando una tarea programada del usuario debe continuar sin una sesión abierta.
pipefail
pipefail es una opción de Bash que hace que una cadena conectada por tuberías devuelva el estado de su comando fallido situado más a la derecha, o cero cuando todos los comandos tienen éxito.
Con pipefail habilitado, una entrada ausente señalada por grep puede hacer que falle toda la cadena de comandos.
Proceso hijo
Un proceso hijo es un proceso iniciado por otro proceso, con su propio estado y valores de entorno heredados.
Un guion en un proceso hijo puede cambiar de directorio sin desplazar el terminal que lo inició.
Protección mediante comillas
La protección mediante comillas controla cómo interpreta Bash los caracteres especiales y mantiene unido el texto deseado mientras prepara los argumentos de los comandos.
Proteger "$file" con comillas conserva «monthly report.txt» como un argumento al copiar el archivo.
Prueba de archivo
Una prueba de archivo comprueba la existencia, el tipo o las propiedades de acceso de una ruta y devuelve un estado que puede usar una condición.
La prueba de archivo [ -d "$src" ] acepta un directorio de origen, pero rechaza un archivo regular.

R

Rama
Una rama es un grupo de comandos seleccionado por una condición o una coincidencia con un patrón, que permite a un guion realizar distintas acciones según la entrada.
Una rama de uso del disco para el umbral más alto debe ir antes de un umbral de advertencia que se solape con él.
read
El comando integrado de Bash read toma una línea de la entrada estándar y almacena sus campos en las variables indicadas en el comando.
Usar read -r -p "Name: " name solicita un nombre y conserva las barras invertidas del texto introducido.
Registro de systemd
El registro de systemd almacena la salida de los servicios y los registros de diagnóstico, lo que permite inspeccionar el trabajo programado después de su ejecución.
La consulta del registro journalctl -u backup.service muestra mensajes de la tarea de copia de seguridad.
Resto o residuo
Un resto o residuo es la cantidad entera que queda después de una división entera; la aritmética de Bash lo obtiene con el operador %.
El resto de $(( 17 % 5 )) es 2 porque tres grupos completos de cinco usan 15.

S

Salida de error estándar
La salida de error estándar es el flujo de salida para mensajes de diagnóstico, separado de la salida estándar para que los datos normales puedan redirigirse de forma independiente.
Un mensaje enviado a la salida de error estándar con >&2 permanece visible cuando la salida estándar va a un archivo.
shift
El comando integrado shift elimina parámetros posicionales iniciales y vuelve a numerar los restantes, reduciendo el número de argumentos.
Después de que shift procese -v, la siguiente palabra de la línea de comandos pasa a ser $1 para el analizador de opciones.
Sustitución de comandos
La sustitución de comandos ejecuta un comando e inserta su salida estándar, eliminando los saltos de línea finales, mediante la forma $(command).
La sustitución de comandos en today=$(date +%F) captura una fecha para usarla en el nombre de un archivo de copia de seguridad.

T

Tabla de tareas de cron
Una tabla de tareas de cron es una programación de entradas de cron, con cinco campos de tiempo y un comando en cada línea de tarea de una tabla personal.
El comando crontab -l muestra la tabla de tareas de cron del usuario actual para que se puedan inspeccionar sus programaciones.
Temporizador de calendario
Un temporizador de calendario busca coincidencias con fechas y horas mediante OnCalendar y puede ejecutar trabajo pendiente cuando Persistent está establecido en true.
Un temporizador de calendario que usa OnCalendar=Mon..Fri 09:00 selecciona las mañanas de lunes a viernes a las 09:00.
Temporizador monotónico
Un temporizador monotónico mide el tiempo transcurrido desde un evento, como el arranque o la última activación del servicio, en lugar de buscar una coincidencia con una hora del calendario.
Un temporizador monotónico puede combinar OnBootSec y OnUnitActiveSec para una primera ejecución e intervalos posteriores.
Trazado de ejecución
El trazado de ejecución muestra los comandos después de su expansión mientras Bash los ejecuta, haciendo visibles los valores usados durante la ejecución para facilitar la depuración.
El trazado de ejecución con bash -x revela un argumento de origen vacío pasado a un comando de copia de archivos.

U

Unidad de servicio
Una unidad de servicio define un trabajo que systemd debe iniciar, como un guion de ejecución única indicado mediante una ruta absoluta en ExecStart.
La unidad de servicio backup.service define el guion que activa el temporizador de copia de seguridad correspondiente.
Unidad de temporizador
Una unidad de temporizador proporciona una programación de systemd que activa otra unidad, normalmente el servicio con el mismo nombre base.
Habilitar la unidad de temporizador backup.timer establece la programación del servicio de copia de seguridad.

V

Validación
La validación comprueba si una entrada cumple los requisitos de un guion antes de que comience el trabajo dependiente, incluidos el número y los tipos de argumentos.
La validación rechaza un directorio cuando un guion de recuento requiere un archivo regular como entrada.
Valor predeterminado
Un valor predeterminado proporciona una entrada opcional cuando no se ha dado un valor utilizable, como ${1:-/var/log} para un argumento ausente o vacío.
Un valor predeterminado permite que un informe programado use un directorio habitual sin solicitarlo a una persona.
Variable
Una variable es un valor con nombre que almacena el intérprete de comandos y que se expande cuando un comando necesita usar el valor asociado a ese nombre.
La variable city almacena «Lisbon» después de city=Lisbon, por lo que echo "$city" puede mostrarlo.
Variable de entorno
Una variable de entorno es un valor con nombre incluido en el entorno que se copia de un proceso a los programas que inicia.
La variable de entorno HOME proporciona una ruta de directorio personal a muchos comandos que inicia un intérprete de comandos.

Sobre esta unidad

Por StudeliInformar de un error

Crea tus propios Materiales de Estudio

Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.

Comenzar