Linux Professional Institute Learning Logo.
Pasar al contenido principal
  • Inicio
    • Todos los recursos
    • LPI Learning Materials
    • Conviértete en colaborador
    • Publishing Partners
    • Conviértase en un Publishing Partner
    • Acerca de nosotros
    • FAQ
    • Colaboradores
    • Contáctenos
  • LPI.org
3.3 Lección 2
Tema 1: La Comunidad Linux y una carrera en el mundo del código abierto
1.1 Los sistemas operativos populares y la evolución de Linux
  • 1.1 Lección 1
1.2 Principales aplicaciones de código abierto
  • 1.2 Lección 1
1.3 Software de Código Abierto y las licencias
  • 1.3 Lección 1
1.4 Destrezas TIC y el trabajo con Linux
  • 1.4 Lección 1
Tema 2: Encontrando el camino en un sistema Linux
2.1 Aspectos básicos de la línea de comandos
  • 2.1 Lección 1
  • 2.1 Lección 2
2.2 Uso de la línea de comandos para obtener ayuda
  • 2.2 Lección 1
2.3 Uso de directorios y listado de archivos
  • 2.3 Lección 1
  • 2.3 Lección 2
2.4 Crear, mover y borrar archivos
  • 2.4 Lección 1
Tema 3: El poder de la línea de comandos
3.1 Archivar ficheros desde la línea de comandos
  • 3.1 Lección 1
3.2 Buscar y extraer datos de los ficheros
  • 3.2 Lección 1
  • 3.2 Lección 2
3.3 Crear un script a partir de una serie de comandos
  • 3.3 Lección 1
  • 3.3 Lección 2
Tema 4: El sistema operativo Linux
4.1 La elección del sistema operativo
  • 4.1 Lección 1
4.2 Conocer el hardware del ordenador
  • 4.2 Lección 1
4.3 Donde los datos se almacenan
  • 4.3 Lección 1
  • 4.3 Lección 2
4.4 Tu ordenador en la red
  • 4.4 Lección 1
Tema 5: Seguridad y sistema de permisos de archivos
5.1 Seguridad básica e identificación de tipos de usuarios
  • 5.1 Lección 1
5.2 Creating Users and Groups
  • 5.2 Lección 1
5.3 Gestión de los permisos y la propiedad de los archivos
  • 5.3 Lección 1
5.4 Directorios y archivos especiales
  • 5.4 Lección 1
  1. Tema 3: El poder de la línea de comandos
  2. 3.3 Crear un script a partir de una serie de comandos
  3. 3.3 Lección 2

3.3 Lección 2

Certificación:

Linux Essentials

Versión:

1.6

Tema:

3 El poder de la línea de comandos

Objetivo:

3.3 Convertiendo comandos en un script

Lección:

2 de 2

Introducción

En la última sección, hemos utilizado este sencillo ejemplo para demostrar el Bash scripting:

#!/bin/bash

# A simple script to greet a single user.

if [ $# -eq 1 ]
then
  username=$1

  echo "Hello $username!"
else
  echo "Please enter only one argument."
fi
echo "Number of arguments: $#."
  • Todos los scripts deben comenzar con un shebang, que define la ruta del intérprete.

  • Todos los scripts deben incluir comentarios para describir su uso.

  • Este script en particular funciona con un argumento, que se pasa al script cuando se llama.

  • Este script contiene una instrucción if que prueba las condiciones de una variable incorporada $#. Esta variable se establece en el número de argumentos.

  • Si el número de argumentos pasados al script es igual a 1, entonces el valor del primer argumento se pasa a una nueva variable llamada username y el script imprime un saludo al usuario. De lo contrario, se muestra un mensaje de error.

  • Finalmente, el script imprime de la cantidad de argumentos. Esto es útil para la depuración.

Este es un ejemplo útil para empezar a explicar algunas de las otras características de Bash scripting.

Códigos de salida

Notarás que nuestro script tiene dos estados posibles: imprime "Hello <user>!" o bien imprime un mensaje de error; lo que es bastante normal para muchas de nuestras utilidades principales. Esto es bastante normal para muchas de nuestras utilidades principales. Considere cat con el que sin duda se ha estado familiarizando mucho.

Comparemos un uso exitoso de cat con una situación donde este falla. Un recordatorio de que nuestro ejemplo anterior es un script llamado new_script.sh.

$ cat -n new_script.sh

     1	#!/bin/bash
     2
     3	# A simple script to greet a single user.
     4
     5	if [ $# -eq 1 ]
     6	then
     7	  username=$1
     8
     9	  echo "Hello $username!"
    10	else
    11	  echo "Please enter only one argument."
    12	fi
    13	echo "Number of arguments: $#."

Este comando tiene éxito, y notará que la bandera -n también tiene números de línea impresos. Estos son muy útiles para depurar scripts, pero por favor tenga en cuenta que no son parte del script.

Ahora vamos a comprobar el valor de una nueva variable incorporada $?. Por ahora, sólo hay que revisar la salida:

$ echo $?
0

Ahora consideremos una situación en la que cat fallará, primero veremos un mensaje de error, y luego comprobaremos el valor de $?.

$ cat -n dummyfile.sh
cat: dummyfile.sh: No such file or directory
$ echo $?
1

La explicación de este comportamiento es el siguiente: cualquier ejecución de la utilidad cat devolverá un código de salida (exit code). Un código de salida nos dirá si el comando tuvo éxito o presentó un error. Un código de salida de cero indica que el comando se completó con éxito; esto es cierto para casi todos los comandos de Linux con los que trabaje. Cualquier otro código de salida indicará un error de algún tipo. El código de salida del último comando para ejecutar se almacenará en la variable $?.

Considere un script en el que podamos estar copiando archivos a una unidad de red remota, ya que hay muchas maneras en las que la tarea de copia puede haber fallado: por ejemplo, nuestra máquina local puede no estar conectada a la red, o la unidad remota puede estar llena, y al comprobar el código de salida de nuestra utilidad de copia, podemos alertar al usuario de problemas al ejecutar el script.

Es una buena práctica implementar códigos de salida, así que lo haremos ahora, tenemos dos caminos en nuestro guión, un éxito y un fracaso, usemos el cero para indicar el éxito y el otro para indicar el fracaso.

     1	#!/bin/bash
     2
     3	# A simple script to greet a single user.
     4
     5	if [ $# -eq 1 ]
     6	then
     7	  username=$1
     8
     9	  echo "Hello $username!"
    10	  exit 0
    11	else
    12	  echo "Please enter only one argument."
    13	  exit 1
    14	fi
    15	echo "Number of arguments: $#."
$ ./new_script.sh Carol
Hello Carol!
$ echo $?
0

Note que el comando echo en la línea 15 fue ignorado por completo, usando exit terminará el script inmediatamente, por lo que esta línea nunca se encontrará.

Manejando Muchos Argumentos

Hasta ahora nuestro script sólo puede manejar un único nombre de usuario a la vez, cualquier número de argumentos además de uno causará un error, vamos a explorar cómo podemos hacer que este script sea más versátil.

El primer instinto de un usuario puede ser usar más variables posicionales como $2, $3, etc. Desafortunadamente, no podemos anticipar el número de argumentos que un usuario puede elegir usar.

Modificaremos la lógica de nuestro script, ya que al no tener ningún argumento debería causar un error, pero cualquier otro número de argumentos debería tener éxito, este nuevo script se llamará friendly2.sh.

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  echo "Hello $@!"
    11	  exit 0
    12	fi
$ ./friendly2.sh Carol Dave Henry
Hello Carol Dave Henry!

Hay dos variables integradas que contienen todos los argumentos pasados al script: $@ y $*. En su mayor parte, ambos se comportan igual. Bash analizará sintácticamente los argumentos y separará cada argumento cuando encuentre un espacio entre ellos. En efecto, el contenido de $@ se ve así:

0

1

2

Carol

Dave

Henry

Si está familiarizado con otros lenguajes de programación, puede reconocer este tipo de variables como un arreglo (array). Las matrices en Bash pueden crearse simplemente poniendo espacio entre elementos como la variable FILES en el script arraytest como a continuación:

FILES="/usr/sbin/accept /usr/sbin/pwck/ usr/sbin/chroot"

Contiene una lista de muchos artículos, lo que hasta ahora no es muy útil, ya que todavía no hemos introducido ninguna forma de manejar estos artículos individualmente.

Bucles (for loop)

Veamos el ejemplo arraytest que se muestra antes. Si recuerdas, en este ejemplo estamos especificando una matriz propia llamada ARCHIVOS. Lo que necesitamos es una forma de “desempaquetar” esta variable y acceder a cada valor individual, uno tras otro. Para hacer esto, utilizaremos una estructura llamada bucles (for loop), que está presente en todos los lenguajes de programación. Hay dos variables a las que nos referiremos: una es el rango y la otra es para el valor individual en el que estamos trabajando actualmente. Este es el script en su totalidad:

#!/bin/bash

FILES="/usr/sbin/accept /usr/sbin/pwck/ usr/sbin/chroot"

for file in $FILES
do
  ls -lh $file
done
$ ./arraytest
lrwxrwxrwx 1 root root 10 Apr 24 11:02 /usr/sbin/accept -> cupsaccept
-rwxr-xr-x 1 root root 54K Mar 22 14:32 /usr/sbin/pwck
-rwxr-xr-x 1 root root 43K Jan 14 07:17 /usr/sbin/chroot

Si te refieres de nuevo al ejemplo de friendly2.sh, puedes ver que estamos trabajando con un rango de valores contenidos dentro de una sola variable $@. Para mayor claridad, llamaremos a esta última variable username:

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  for username in $@
    11	  do
    12	    echo "Hello $username!"
    13	  done
    14	  exit 0
    15	fi

Recuerda que la variable que definas aquí puede llamarse como quieras, y que todas las líneas dentro de do…​. done se ejecutarán una vez para cada elemento del array:

$ ./friendly2.sh Carol Dave Henry
Hello Carol!
Hello Dave!
Hello Henry!

Ahora supongamos que queremos hacer que nuestra producción parezca un poco más humana, queremos que nuestro saludo sea en una sola línea.

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  echo -n "Hello $1"
    11	  shift
    12	  for username in $@
    13	  do
    14	    echo -n ", and $username"
    15	  done
    16	  echo "!"
    17	  exit 0
    18	fi

Un par de notas:

  • Usando -n con echo suprimirá la nueva línea después de imprimir, lo que significa que todos los ecos se imprimirán en la misma línea, y la nueva línea se imprimirá sólo después de ! en la línea 16.

  • El comando shift eliminará el primer elemento de nuestro array, por lo que esto es así:

0

1

2

Carol

Dave

Henry

Se convierte en esto:

0

1

Dave

Henry

Observemos la salida:

$ ./friendly2.sh Carol
Hello Carol!
$ ./friendly2.sh Carol Dave Henry
Hello Carol, and Dave, and Henry!

Uso de expresiones regulares para realizar la comprobación de errores

Es posible que queramos verificar todos los argumentos que el usuario está introduciendo, por ejemplo, quizás queramos asegurarnos de que todos los nombres pasados a friendly2.sh contienen sólo letras, y cualquier carácter o número especial causará un error, para ello usaremos grep.

Recordemos que podemos usar expresiones regulares con grep.

$ echo Animal | grep "^[A-Za-z]*$"
Animal
$ echo $?
0
$ echo 4n1ml | grep "^[A-Za-z]*$"
$ echo $?
1

El ^ y el $ indican el principio y el final de la línea respectivamente, el [A-Za-z] indica un rango de letras, mayúsculas o minúsculas, el * es un cuantificador, y modifica nuestro rango de letras de manera que estamos haciendo coincidir el cero con muchas letras. En resumen, nuestro grep tendrá éxito si la entrada es solo letras, y fallará si fuera lo contrario.

Lo siguiente que hay que tener en cuenta es que grep es devolver los códigos de salida en función de si hubo una coincidencia o no, una coincidencia positiva devuelve 0, y una no coincidencia devuelve 1. Podemos usar esto para probar nuestros argumentos dentro de nuestro script.

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  for username in $@
    11	  do
    12	    echo $username | grep "^[A-Za-z]*$" > /dev/null
    13	    if [ $? -eq 1 ]
    14	    then
    15	      echo "ERROR: Names must only contains letters."
    16	      exit 2
    17	    else
    18	      echo "Hello $username!"
    19	    fi
    20	  done
    21	  exit 0
    22	fi

En la línea 12, estamos redirigiendo la salida estándar a /dev/null, la cual es una forma sencilla de suprimirla. No queremos ver ninguna salida del comando grep, sólo queremos probar su código de salida en lo que ocurre en la línea 13. Note también que estamos usando un código de salida de 2 para indicar un argumento inválido, por lo general es una buena práctica usar diferentes códigos de salida para indicar diferentes errores; de esta manera, un usuario experto puede usar estos códigos de salida para resolver problemas.

$ ./friendly2.sh Carol Dave Henry
Hello Carol!
Hello Dave!
Hello Henry!
$ ./friendly2.sh 42 Carol Dave Henry
ERROR: Names must only contains letters.
$ echo $?
2

Ejercicios guiados

  1. Lea el contenido de script1.sh a continuación:

    #!/bin/bash
    
    if [ $# -lt 1 ]
    then
      echo "This script requires at least 1 argument."
      exit 1
    fi
    
    echo $1 | grep "^[A-Z]*$" > /dev/null
    if [ $? -ne 0 ]
    then
      echo "no cake for you!"
      exit 2
    fi
    
    echo "here's your cake!"
    exit 0

    ¿Cuál es el resultado de estos comandos?

    • ./script1.sh

    • echo $?

    • ./script1.sh cake

    • echo $?

    • ./script1.sh CAKE

    • echo $?

  2. Lea el contenido del archivo script2.sh:

    for filename in $1/*.txt
    do
       cp $filename $filename.bak
    done

    Describa el propósito de este script tal como lo entiende.

Ejercicios exploratorios

  1. Cree una secuencia de comandos que tome cualquier número de argumentos del usuario e imprima solo aquellos argumentos que sean números mayores a 10.

Resumen

En esta lección usted aprendió:

  • ¿Qué son los códigos de salida, que significan y como implementarlos?

  • ¿Cómo verificar el código de salida de un comando?

  • ¿Qué son los bucles for y como usarlos con matrices?

  • ¿Cómo usar grep, expresiones regulares y códigos de salida para verificar la entrada del usuario en los scripts?

Comandos utilizados en los ejercicios:

shift

Esto eliminará el primer elemento de una matriz..

Variables especiales:

$?

Contiene el código de salida del último comando ejecutado.

$@, $*

Contiene todos los argumentos pasados al script, como una matriz.

Respuestas a los ejercicios guiados

  1. Lea el contenido de script1.sh a continuación:

    #!/bin/bash
    
    if [ $# -lt 1 ]
    then
      echo "This script requires at least 1 argument."
      exit 1
    fi
    
    echo $1 | grep "^[A-Z]*$" > /dev/null
    if [ $? -ne 0 ]
    then
      echo "no cake for you!"
      exit 2
    fi
    
    echo "here's your cake!"
    exit 0

    ¿Cuál es el resultado de estos comandos?

    • comando: ./script1.sh

      Salida: This script requires at least 1 argument.

    • comando: echo $?

      Salida: 1

    • comando: ./script1.sh cake

      Salida: no cake for you!

    • comando: echo $?

      Salida: 2

    • comando: ./script1.sh CAKE

      Salida: here’s your cake!

    • comando: echo $?

      Salida: 0

  2. Lea el contenido del archivo script2.sh:

    for filename in $1/*.txt
    do
       cp $filename $filename.bak
    done

    Describa el propósito de este script tal como lo entiende.

    Este script realizará copias de seguridad de todos los archivos que terminen con .txt en un subdirectorio definido en el primer argumento.

Respuestas a los ejercicios exploratorios

  1. Cree una secuencia de comandos que tome cualquier número de argumentos del usuario e imprima solo aquellos argumentos que sean números mayores a 10.

    #!/bin/bash
    
    for i in $@
    do
      echo $i | grep "^[0-9]*$" > /dev/null
      if [ $? -eq 0 ]
      then
        if [ $i -gt 10 ]
        then
          echo -n "$i "
        fi
      fi
    done
    echo ""

© 2020 Linux Professional Insitute Inc. Todos los derechos reservados. Visite el sitio web de Learning Materials: https://asir.sudo.es/docnux/learning.lpi.org
Este trabajo está registrado bajo la Licencia Internacional Creative Commons Attribution-NonCommercial-NoDerivatives 4.0

Siguiente lección

4.1 La elección del sistema operativo (4.1 Lección 1)

Leer la próxima lección

© 2020 Linux Professional Insitute Inc. Todos los derechos reservados. Visite el sitio web de Learning Materials: https://asir.sudo.es/docnux/learning.lpi.org
Este trabajo está registrado bajo la Licencia Internacional Creative Commons Attribution-NonCommercial-NoDerivatives 4.0

LPI es una organización sin fines de lucro.

Linux Professional Institute (LPI) es la organización global de certificación y apoyo académico para profesionales de código abierto. Con más de 200,000 titulares de certificación, es el primer y más grande organismo de certificación no comercial del mundo para Linux y Open Source. LPI cuenta con profesionales certificados en más de 180 países, realiza exámenes en varios idiomas y tiene cientos de socios de capacitación.

Nuestro propósito es hacer que las oportunidades económicas y creativas estén disponibles para todos, haciendo que el conocimiento de código abierto y la certificación sea universalmente accesible.

  • LinkedIn
  • flogo-RGB-HEX-Blk-58 Facebook
  • Twitter
  • Contáctenos
  • Política de privacidad y cookies

¿Detecta un error o desea ayudar a mejorar esta página? Por favor háznoslo saber.

© Copyright 1999-2020 The Linux Professional Institute Inc. Todos los derechos reservados.