GNU/Linux >> Tutoriales Linux >  >> Linux

Introducción a la programación de Linux Bash:5 consejos de bucle `for`

Todos los administradores de sistemas probablemente tienen alguna habilidad que han aprendido a lo largo de los años que pueden señalar y decir:"Eso cambió mi mundo". Esa habilidad, o ese poco de información, o esa técnica simplemente cambió la forma en que hago las cosas. Para muchos de nosotros, eso es bucle en bash. Hay otros enfoques de la automatización que sin duda son más robustos o escalables. La mayoría de ellos no se comparan con la simplicidad y facilidad de uso del for bucle, sin embargo.

Si desea automatizar la configuración de miles de sistemas, probablemente debería usar Ansible. Sin embargo, si intenta cambiar el nombre de miles de archivos o ejecutar el mismo comando varias veces, entonces for loop es definitivamente la herramienta adecuada para el trabajo.

[ También te puede interesar: Dominar bucles con plantillas Jinja en Ansible ]

Si ya tiene experiencia en programación o secuencias de comandos, probablemente esté familiarizado con lo que for los bucles sí. Si no es así, intentaré desglosarlo en un lenguaje sencillo para usted.

El concepto básico es: PARA un conjunto dado de artículos, DO una cosa.

El conjunto dado de elementos puede ser un conjunto literal de objetos o cualquier cosa que Bash pueda extrapolar a una lista. Por ejemplo, el texto extraído de un archivo, la salida de otro comando Bash o los parámetros pasados ​​a través de la línea de comando. Convertir esta estructura de bucle en un script Bash también es trivial. En este artículo, le mostramos algunos ejemplos de cómo un for loop puede hacerte lucir como un héroe de la línea de comandos, y luego tomamos algunos de esos ejemplos y los colocamos dentro de un script Bash más estructurado.

Estructura básica del bucle for

Primero, hablemos de la estructura básica de un for loop, y luego veremos algunos ejemplos.

La sintaxis básica de un for el bucle es:

for <variable name> in <a list of items>;do <some command> $<variable name>;done;

El nombre de la variable será la variable que especifique en el do sección y contendrá el elemento en el bucle en el que se encuentra.

La lista de elementos puede ser cualquier cosa que devuelva una lista separada por espacios o saltos de línea.

He aquí un ejemplo:

$ for name in joey suzy bobby;do echo $name;done

Eso es tan simple como parece y no hay mucho que hacer allí, pero lo ayuda a comenzar. La variable $nombre contendrá el elemento en la lista en la que el bucle está operando actualmente, y una vez que el comando (o comandos) en el do se llevan a cabo, el bucle se moverá al siguiente elemento. También puede realizar más de una acción por bucle. Cualquier cosa entre do y done será ejecutado. Los nuevos comandos solo necesitan un ; delimitándolos.

$ for name in joey suzy bobby; do echo first $name;echo second $name;done;
first joey
second joey
first suzy
second suzy
first bobby
second bobby

Ahora un poco de real ejemplos.

Renombrar archivos

Este ciclo toma la salida del comando Bash ls *.pdf y realiza una acción en cada nombre de archivo devuelto. En este caso, agregaremos la fecha de hoy al final del nombre del archivo (pero antes de la extensión del archivo).

for i in $(ls *.pdf); do
mv $i $(basename $i .pdf)_$(date +%Y%m%d).pdf
done

Para ilustrar, ejecute este bucle en un directorio que contenga estos archivos:

file1.pdf
file2.pdf
...
fileN.pdf

Los archivos se renombrarán así:

file1_20210210.pdf
file2_20210210.pdf
...
fileN_20210210.pdf

En un directorio con cientos de archivos, este ciclo le ahorra una cantidad considerable de tiempo al renombrarlos a todos.

Extrapolación de listas de elementos

Imagina que tienes un archivo que deseas scp a varios servidores. Recuerda que puedes combinar el for bucle con otras funciones de Bash, como la expansión de shell, que le permite a Bash expandir una lista de elementos que están en una serie. Esto puede funcionar para letras y números. Por ejemplo:

$ echo {0..10}
0 1 2 3 4 5 6 7 8 9 10

Suponiendo que sus servidores se nombran en algún tipo de patrón como, web0 , web1 , web2 , web3 , puede hacer que Bash itere la serie de números de esta manera:

$ for i in web{0..10};do scp somefile.txt ${i}:;done;

Esto iterará a través de web0 , web1 , web2 , web3 , y así sucesivamente, ejecutando su comando en cada elemento.

También puede definir algunas iteraciones. Por ejemplo:

$ for i in web{0..10} db{0..2} balance_{a..c};do echo $i;done
web0
web1
web2
web3
web4
web5
web6
web7
web8
web9
web10
db0
db1
db2
balance_a
balance_b
balance_c

También puede combinar iteraciones. Imagine que tiene dos centros de datos, uno en los Estados Unidos y otro en Canadá, y la convención de nomenclatura del servidor identifica en qué centro de datos vivía un par de servidores HA. Por ejemplo, web-us-0 sería el primer servidor web en el centro de datos de EE. UU., mientras que web-ca-0 serían web 0's contraparte en el centro de datos de CA. Para ejecutar algo en ambos sistemas, puede usar una secuencia como esta:

$ for i in web-{us,ca}-{0..3};do echo $i;done
web-us-0
web-us-1
web-us-2
web-us-3
web-ca-0
web-ca-1
web-ca-2
web-ca-3

En caso de que los nombres de su servidor no sean fáciles de iterar, puede proporcionar una lista de nombres a for bucle:

$ cat somelist
first_item
middle_things
foo
bar
baz
last_item

$ for i in `cat somelist`;do echo "ITEM: $i";done
ITEM: first_item
ITEM: middle_things
ITEM: foo
ITEM: bar
ITEM: baz
ITEM: last_item

Anidación

También puede combinar algunas de estas ideas para casos de uso más complejos. Por ejemplo, imagina que quieres copiar una lista de archivos a tus servidores web que siguen la convención de nomenclatura numerada que usaste en el ejemplo anterior.

Puede lograrlo iterando una segunda lista basada en su primera lista a través de bucles anidados. Esto se vuelve un poco difícil de seguir cuando lo haces de una sola línea, pero definitivamente se puede hacer. Tu for anidado el bucle se ejecuta en cada iteración del padre for círculo. Asegúrese de especificar diferentes nombres de variables para cada bucle.

Para copiar la lista de archivos archivo1.txt, archivo2.txt, y archivo3.txt a los servidores web, use este bucle anidado:

$ for i in file{1..3};do for x in web{0..3};do echo "Copying $i to server $x"; scp $i $x; done; done
Copying file1 to server web0
Copying file1 to server web1
Copying file1 to server web2
Copying file1 to server web3
Copying file2 to server web0
Copying file2 to server web1
Copying file2 to server web2
Copying file2 to server web3
Copying file3 to server web0
Copying file3 to server web1
Copying file3 to server web2
Copying file3 to server web3

Cambio de nombre más creativo

Puede haber otras formas de hacer esto, pero recuerda, este es solo un ejemplo de las cosas que puedes hacer con un for círculo. ¿Qué sucede si tiene una montaña de archivos con un nombre similar a FILE002.txt? y desea reemplazar FILE con algo como TEXTO . Recuerda que además del propio Bash, también tienes a tu disposición otras herramientas de código abierto, como sed , grep , y más. Puede combinar esas herramientas con for bucle, así:

$ ls FILE*.txt
FILE0.txt  FILE10.txt  FILE1.txt  FILE2.txt  FILE3.txt  FILE4.txt  FILE5.txt  FILE6.txt  FILE7.txt  FILE8.txt  FILE9.txt

$ for i in $(ls FILE*.txt);do mv $i `echo $i | sed s/FILE/TEXT/`;done

$ ls FILE*.txt
ls: cannot access 'FILE*.txt': No such file or directory

$ ls TEXT*.txt
TEXT0.txt  TEXT10.txt  TEXT1.txt  TEXT2.txt  TEXT3.txt  TEXT4.txt  TEXT5.txt  TEXT6.txt  TEXT7.txt  TEXT8.txt  TEXT9.txt

Agregar un bucle for a un script Bash

Ejecutando for Los bucles directamente en la línea de comandos son excelentes y le ahorran una cantidad considerable de tiempo para algunas tareas. Además, puede incluir for bucles como parte de sus scripts de Bash para aumentar la potencia, la legibilidad y la flexibilidad.

Por ejemplo, puede agregar el ejemplo de bucle anidado a un script de Bash para mejorar su legibilidad, así:

$ vim copy_web_files.sh
# !/bin/bash

for i in file{1..3};do
  for x in web{0..3};do
    echo "Copying $i to server $x"
    scp $i $x
  done
done

Cuando guarda y ejecuta este script, el resultado es el mismo que ejecutar el ejemplo de bucle anidado anterior, pero es más legible, además es más fácil de cambiar y mantener.

$ bash copy_web_files.sh
Copying file1 to server web0
Copying file1 to server web1
... TRUNCATED ...
Copying file3 to server web3

También puede aumentar la flexibilidad y la reutilización de su for bucles incluyéndolos en los scripts de Bash que permiten la entrada de parámetros. Por ejemplo, para cambiar el nombre de archivos como el ejemplo Renombramiento más creativo anterior que permite al usuario especificar el sufijo del nombre, use este script:

$ vim rename_files.sh
# !/bin/bash

source_prefix=$1
suffix=$2
destination_prefix=$3

for i in $(ls ${source_prefix}*.${suffix});do
  mv $i $(echo $i | sed s/${source_prefix}/${destination_prefix}/)
done

En este script, el usuario proporciona el prefijo del archivo de origen como primer parámetro, el sufijo del archivo como segundo y el nuevo prefijo como tercer parámetro. Por ejemplo, para cambiar el nombre de todos los archivos que comienzan con FILE , de tipo .txt a TEXTO , ejecute el script así:

$ ls FILE*.txt
FILE0.txt  FILE10.txt  FILE1.txt  FILE2.txt  FILE3.txt  FILE4.txt  FILE5.txt  FILE6.txt  FILE7.txt  FILE8.txt  FILE9.txt

$ bash rename_files.sh FILE txt TEXT

$ ls TEXT*.txt
TEXT0.txt  TEXT10.txt  TEXT1.txt  TEXT2.txt  TEXT3.txt  TEXT4.txt  TEXT5.txt  TEXT6.txt  TEXT7.txt  TEXT8.txt  TEXT9.txt

Esto es similar al ejemplo original, pero ahora sus usuarios pueden especificar otros parámetros para cambiar el comportamiento del script. Por ejemplo, para cambiar el nombre de todos los archivos que ahora comienzan con TEXT a NUEVO , utilice lo siguiente:

$ bash rename_files.sh TEXT txt NEW

$ ls NEW*.txt
NEW0.txt  NEW10.txt  NEW1.txt  NEW2.txt  NEW3.txt  NEW4.txt  NEW5.txt  NEW6.txt  NEW7.txt  NEW8.txt  NEW9.txt

[ Un curso gratuito para usted:Resumen técnico de virtualización y migración de infraestructura. ] 

Conclusión

Con suerte, estos ejemplos han demostrado el poder de un for bucle en la línea de comandos de Bash. Realmente puede ahorrar mucho tiempo y realizar tareas de una manera menos propensa a errores con bucles. Sólo sé cuidadoso. Tus bucles harán lo que les pidas, incluso si les pides que hagan algo destructivo por accidente, como crear (o eliminar) volúmenes lógicos o discos virtuales.

Esperamos que Bash for los bucles cambian tu mundo de la misma manera que cambiaron el nuestro.


Linux
  1. Cómo escribir un bucle en Bash

  2. Prepara tu indicador de Bash para el invierno en Linux

  3. Introducción a Nmap en Kali Linux

  4. Lenguaje de programación C - Introducción

  5. Scripts de Linux:3 procedimientos para bucles while en Bash

Golpe para bucle

Golpear hasta bucle

Comando de historial en Linux (Bash History)

Una introducción al navegador Vivaldi en Linux

5 consejos para dominar Linux

20 consejos de programación Killer Perl para principiantes en UNIX / Linux OS