La guía para principiantes de Shell Scripting 2: For Loops



Si desea aumentar su credibilidad geek, únase a nosotros para la segunda entrega de nuestra serie de scripts de shell. Tenemos algunas correcciones, algunas mejoras en el guión de la semana pasada y una guía sobre bucles para los no iniciados.

El script de datecp revisado

En el primera entrega de nuestra guía de secuencias de comandos de shell , creamos un script que copiaba un archivo a un directorio de respaldo después de agregar la fecha al final del nombre del archivo.





Samuel Dionne-Riel señaló en los comentarios que hay una manera mucho mejor de manejar nuestras referencias variables.

Los argumentos están separados por espacios en el shell bash, se tokenizará cuando haya un espacio en el comando expandido resultante. En su guión, cp .$date_formatted funcionará según lo previsto siempre que las variables expandidas no tengan espacios. Si llama a su script de esta manera: datecp 'my old name' 'my new name' la expansión resultará en este comando: cp my new name my old name.the_date que en realidad tiene 6 argumentos.



Para abordar correctamente este problema, la última línea del script debe ser: cp '' '.$date_formatted'

Como puede ver, cambiando la línea de nuestro script de:

cp -iv $ 1 $ 2. $ fecha_formateada



a:

cp -iv $ 1 $ 2. $ fecha_formateada

se encargará de este problema cuando utilice el script en archivos que tengan espacios en el nombre. Samuel también hace hincapié en que al copiar y pegar código de este sitio (o de Internet en general), asegúrese de sustituir los guiones y comillas adecuados por los que suelen ser mejores y que suelen reemplazarlos. También haremos más para asegurarnos de que nuestro código sea más fácil de copiar y pegar. ;-)

Otro comentarista, Myles Braithwaite, decidió expandir nuestro script para que la fecha apareciera antes de la extensión del archivo. Entonces en lugar de

deliciousfile.mp3.07_14_11-12.34.56

obtendríamos esto:

deliciousfile.07_14_11-12.34.56.mp3

Anuncio publicitario

lo que termina siendo un poco más conveniente para la mayoría de los usuarios. Su código está disponible en el su página de GitHub . Echemos un vistazo a lo que usa para separar el nombre del archivo.

date_formatted = $ (fecha +% Y-% m-% d_% H.% M% S)
file_extension = $ (echo $ 1 ″ | awk -F. ‘{print $ NF}’)
nombre_archivo = $ (nombre base $ 1. $ extensión_archivo)

cp -iv $ 1 $ nombre_archivo- $ formato_fecha. $ extensión_archivo

He cambiado un poco el formato, pero puede ver que Myles declara su función de fecha en la Línea 1. En la Línea 2, sin embargo, usa el comando echo con el primer argumento del script para generar el nombre del archivo. Él usa el comando de tubería para tomar esa salida y usarla como entrada para la siguiente parte. Después de la tubería, Myles invoca el comando awk, que es un poderoso programa de escaneo de patrones. Usando la bandera -F, le está diciendo al comando que el siguiente carácter (después de un espacio) es lo que definirá el separador de campo. En este caso, eso es un punto.

Ahora, awk ve un archivo llamado deliciousfile.mp3 compuesto por dos campos: deliciousfile y mp3. Por último, usa

'{Print $ NF}'

para mostrar el último campo. En caso de que su archivo tenga varios períodos, por lo que awk verá varios campos, solo mostrará el último, que es la extensión del archivo.

En la línea 3, crea una nueva variable para el nombre del archivo y usa el comando basename para hacer referencia a todo en $ 1 excepto la extensión del archivo. Esto se hace usando el nombre base y dándole $ 1 como argumento, luego agregando un espacio y la extensión del archivo. La extensión del archivo se agrega automáticamente debido a la variable que hace referencia a la Línea 2. Lo que esto haría es tomar

deliciousfile.mp3

y conviértelo en

sabroso archivo

Luego, en la última línea, Myles armó el comando que mostrará todo en orden. Tenga en cuenta que no hay ninguna referencia a $ 2, un segundo argumento para el script. Este script en particular copiará dicho archivo en su directorio actual. ¡Buen trabajo Samuel y Myles!

Ejecución de scripts y $ PATH

También mencionamos en nuestro artículo de Conceptos básicos que los scripts no pueden ser referenciados como comandos de forma predeterminada. Es decir, debe apuntar a la ruta del script para ejecutarlo:

./texto

~ / bin / script

Anuncio publicitario

Pero, al colocar sus scripts en ~ / bin /, podría simplemente escribir sus nombres desde cualquier lugar para que se ejecuten.

Los comentaristas pasaron algún tiempo debatiendo qué tan apropiado era esto, ya que ninguna distribución moderna de Linux crea ese directorio de forma predeterminada. Además, nadie lo agrega a la variable $ PATH de forma predeterminada tampoco, que es lo que se requiere para que los scripts se ejecuten como comandos. Estaba un poco desconcertado porque después de verificar mi variable $ PATH, los comentaristas tenían razón, pero llamar a los scripts aún funcionaba para mí. Descubrí por qué: muchas distribuciones modernas de Linux crean un archivo especial en el directorio de inicio del usuario: .profile.

perfil de puntos

Este archivo es leído por bash (a menos que .bash_profile esté presente en el directorio de inicio del usuario) y en la parte inferior, hay una sección que agrega la carpeta ~ / bin / a la variable $ PATH si existe. Entonces, ese misterio se aclara. Durante el resto de la serie, seguiré colocando scripts en el directorio ~ / bin / porque son scripts de usuario y los usuarios deberían poder ejecutarlos. Y, parece que realmente no necesitamos jugar con la variable $ PATH a mano para que las cosas funcionen.

Comandos repetidos con bucles

Vayamos a una de las herramientas más útiles del arsenal de geek para hacer frente a tareas repetitivas: los bucles. Hoy, discutiremos los bucles for.

El esquema básico de un bucle for es el siguiente:

para VARIABLE en LISTA; hacer
comando1
comando2

mando
hecho

VARIABLE puede ser cualquier variable, aunque la mayoría de las veces se usa la i minúscula por convención. LIST es una lista de elementos; puede especificar varios elementos (separándolos por un espacio), apuntar a un archivo de texto externo o usar un asterisco (*) para indicar cualquier archivo en el directorio actual. Los comandos enumerados están sangrados por convención, por lo que es más fácil ver el anidamiento: colocar bucles en bucles (para que pueda bucle mientras lo hace).

Anuncio publicitario

Debido a que las listas usan espacios como delimitadores, es decir, un espacio significa un movimiento al siguiente elemento de la lista, los archivos que tienen espacios en el nombre no son muy amigables. Por ahora, sigamos trabajando con archivos sin espacios. Comencemos con un script simple para mostrar los nombres de los archivos en el directorio actual. Cree un nuevo script en su carpeta ~ / bin / titulado loopscript. Si no recuerda cómo hacer esto (incluido marcarlo como ejecutable y agregar el truco hash bang) consulte nuestra artículo básico sobre secuencias de comandos de bash .

En él, ingrese el siguiente código:

para i en artículo1 artículo2 artículo3 artículo4 artículo5 artículo6; hacer
echo $ i
hecho

lista de eco

Cuando ejecute el script, debería obtener esos elementos de la lista como salida.

lista de eco

Bastante simple, ¿verdad? Veamos qué pasa si cambiamos un poco las cosas. Cambie su secuencia de comandos para que diga esto:

para yo en *; hacer
echo $ i
hecho

echo nombres de archivo

Cuando ejecuta este script en una carpeta, debe obtener una lista de los archivos que contiene como salida.

hacer eco de los nombres de archivo

Ahora, cambiemos el comando echo por algo más útil, digamos, el comando zip. Es decir, agregaremos archivos a un archivo. ¡Y consigamos algunos argumentos en la mezcla!

para i en $ @; hacer
archivo zip $ i
hecho

zip argumentos

¡Hay algo nuevo! $ @ es un atajo para $ 1 $ 2 $ 3… $ n. En otras palabras, es la lista completa de todos los argumentos que especificó. Ahora, observe lo que sucede cuando ejecuto el script con varios archivos de entrada.

zip argumentos

Anuncio publicitario

Puede ver qué archivos están en mi carpeta. Ejecuté el comando con seis argumentos y cada archivo se agregó a un archivo comprimido llamado archive.zip. Fácil, ¿verdad?

Los bucles for son bastante maravillosos. Ahora puede ejecutar funciones por lotes en listas de archivos. Por ejemplo, puede copiar todos los argumentos de su secuencia de comandos en un archivo comprimido, mover los originales a una carpeta diferente y copia segura automáticamente ese archivo zip a una computadora remota. Si configura archivos clave con SSH, ni siquiera necesitará ingresar su contraseña, ¡e incluso puede decirle al script que elimine el archivo zip después de cargarlo!


El uso de bucles for facilita la realización de varias acciones para todos los archivos de un directorio. Puede apilar una amplia variedad de comandos y usar argumentos muy fácilmente para crear una lista sobre la marcha, y esto es solo la punta del iceberg.

Bash scripters, ¿tienen alguna sugerencia? ¿Ha creado una secuencia de comandos útil que utiliza bucles? ¿Quieres compartir tus pensamientos sobre la serie? ¡Deje algunos comentarios y ayude a otros novatos en la creación de scripts!

LEER SIGUIENTE

Artículos De Interés