Guide du débutant pour Shell Scripting 2 For Loops
Si vous souhaitez développer votre credo geek, rejoignez-nous pour le deuxième volet de notre série de scripts shell. Nous avons quelques corrections, quelques améliorations au script de la semaine dernière et un guide sur la mise en boucle pour les non-initiés..
Le script datecp revisité
Dans la première partie de notre guide de script shell, nous avons créé un script qui copiait un fichier dans un répertoire de sauvegarde après avoir ajouté la date à la fin du nom du fichier..
Samuel Dionne-Riel a souligné dans ses commentaires qu'il existe une bien meilleure façon de gérer nos références variables.
Les arguments sont séparés par des espaces dans le shell bash, ils seront marqués quand il y aura un espace dans la commande développée résultante. Dans votre script,
cp $ 1 $ 2. $ date_formatted
fonctionnera comme prévu tant que les variables développées n’ont pas d’espace. Si vous appelez votre script de cette façon:datecp "mon ancien nom" "mon nouveau nom"
l'expansion entraînera cette commande:cp mon nouveau nom mon ancien nom.la_date
qui a en fait 6 arguments.Pour résoudre correctement ce problème, la dernière ligne du script devrait être:
cp "$ 1" "$ 2. $ date_formatted"
Comme vous pouvez le voir, changer la ligne de notre script de:
cp -iv $ 1 $ 2. $ date_formatted
à:
cp -iv “$ 1” “$ 2”. $ date_formatted
résoudra ce problème lors de l'utilisation du script sur des fichiers comportant des espaces dans le nom. Samuel souligne également que, lors de la copie et du collage de code provenant de ce site (ou d'Internet en général), veillez à substituer les tirets appropriés aux citations «mieux typographiquement» qui les remplacent souvent. Nous ferons également davantage pour nous assurer que notre code est plus convivial en copier / coller. ;-)
Un autre intervenant, Myles Braithwaite, a décidé d’élargir notre script afin que la date apparaisse avant l’extension du fichier. Donc au lieu de
tastyfile.mp3.07_14_11-12.34.56
nous aurions ceci:
tastyfile.07_14_11-12.34.56.mp3
ce qui finit par être un peu plus pratique pour la plupart des utilisateurs. Son code est disponible sur sa page GitHub. Voyons ce qu'il utilise pour séparer le nom de fichier.
date_formatted = $ (date +% Y-% m-% d_% H.% M% S)
fichier_extension = $ (echo “$ 1" | awk -F. 'print $ NF')
nom_fichier = $ (nom de base $ 1. $ extension_fichier)cp -iv $ 1 $ nom_fichier- $ date_formatée. $ extension_fichier
J'ai un peu modifié la mise en forme, mais vous pouvez voir que Myles déclare sa fonction de date dans la ligne 1. Toutefois, dans la ligne 2, il utilise la commande «echo» avec le premier argument du script pour afficher le nom du fichier. Il utilise la commande pipe pour prendre cette sortie et l'utiliser comme entrée pour la partie suivante. Après le tuyau, Myles appelle la commande «awk», un programme puissant d’analyse de motifs. En utilisant le drapeau -F, il dit à la commande que c'est le caractère suivant (après un espace) qui définira le «séparateur de champs». Dans ce cas, c'est une période.
Maintenant, awk voit un fichier nommé "tastyfile.mp3" composé de deux champs: "tastyfile" et "mp3". Enfin, il utilise
'print $ NF'
pour afficher le dernier champ. Si votre fichier contient plusieurs points (ce qui oblige awk à voir plusieurs champs), il n’affiche que le dernier, l’extension de fichier..
Dans la ligne 3, il crée une nouvelle variable pour le nom du fichier et utilise la commande «basename» pour référencer tout ce qui se trouve dans $ 1. sauf l'extension de fichier. Ceci est fait en utilisant basename et en lui donnant l'argument $ 1, puis en ajoutant un espace et l'extension du fichier. L’extension de fichier est automatiquement ajoutée en raison de la variable qui fait référence à la ligne 2. Cela prendrait ceci:
tastyfile.mp3
et le transformer en
savoureuxfile
Puis, à la dernière ligne, Myles met en place la commande qui va tout afficher dans l’ordre. Notez qu'il n'y a pas de référence à $ 2, un deuxième argument pour le script. Ce script particulier copiera ledit fichier dans votre répertoire actuel à la place. Excellent travail Samuel et Myles!
Scripts en cours d'exécution et $ PATH
Nous mentionnons également dans notre article de base que les scripts ne peuvent pas être référencés en tant que commandes par défaut. En d’autres termes, vous devez indiquer le chemin du script pour l’exécuter:
./scénario
~ / bin / script
Mais, en plaçant vos scripts dans ~ / bin /, vous pouvez simplement taper leurs noms où que vous soyez pour les faire fonctionner..
Les commentateurs ont passé un certain temps à débattre de la pertinence de cette opération, car aucune distribution Linux moderne ne crée ce répertoire par défaut. De plus, personne ne l'ajoute à la variable $ PATH par défaut non plus, ce qui est nécessaire pour que les scripts soient exécutés comme des commandes. J'étais un peu perplexe car après avoir vérifié ma variable $ PATH, les commentateurs avaient raison, mais appeler des scripts fonctionnait toujours pour moi. J'ai découvert pourquoi: de nombreuses distributions Linux modernes créent un fichier spécial dans le répertoire personnel de l'utilisateur - .profile.
Ce fichier est lu par bash (à moins que .bash_profile ne soit présent dans le répertoire de base de l'utilisateur) et en bas, une section ajoute le dossier ~ / bin / à la variable $ PATH, le cas échéant. Donc, ce mystère est éclairci. Pour le reste de la série, je continuerai à placer des scripts dans le répertoire ~ / bin /, car ce sont des scripts utilisateur qui devraient pouvoir être exécutés par les utilisateurs. Et, il semble que nous n’ayons pas vraiment besoin de jouer avec la variable $ PATH à la main pour que les choses fonctionnent.
Répéter les commandes avec des boucles
Passons à l’un des outils les plus utiles de l’arsenal geek pour traiter des tâches répétitives: les boucles. Aujourd'hui, nous allons discuter des boucles "for".
La structure de base d’une boucle for est la suivante:
pour VARIABLE dans la liste; faire
commande1
commande2
…
commandn
terminé
VARIABLE peut être n’importe quelle variable, bien que le plus souvent, le «i» minuscule soit utilisé par convention. LISTE est une liste d'éléments; vous pouvez spécifier plusieurs éléments (en les séparant par un espace), pointer vers un fichier texte externe ou utiliser un astérisque (*) pour désigner tout fichier du répertoire en cours. Les commandes répertoriées sont mises en retrait par convention, il est donc plus facile de voir l'imbrication - mettre des boucles dans des boucles (afin que vous puissiez boucler pendant que vous bouclez).
Comme les listes utilisent des espaces en tant que délimiteurs - en d’autres termes, un espace signifie un déplacement vers l’élément suivant de la liste - les fichiers dont le nom contient des espaces ne sont pas très conviviaux. Pour l'instant, contentons-nous de travailler avec des fichiers sans espaces. Commençons par un simple script pour afficher les noms des fichiers dans le répertoire en cours. Créez un nouveau script dans votre dossier ~ / bin / intitulé «Loopscript». Si vous ne vous rappelez pas comment faire cela (notamment en le marquant comme exécutable et en ajoutant le hash bang hack), reportez-vous à notre article Notions de base sur les scripts bash.
Dans celui-ci, entrez le code suivant:
pour i dans item1 item2 item3 item4 item5 item6; faire
echo “$ i”
terminé
Lorsque vous exécutez le script, vous devriez simplement obtenir ces éléments de liste en sortie..
Assez simple, non? Voyons ce qui se passe si nous changeons un peu les choses. Changez votre script pour qu'il dise ceci:
pour i in *; faire
echo “$ i”
terminé
Lorsque vous exécutez ce script dans un dossier, vous devriez obtenir une liste des fichiers qu’il contient en sortie..
Maintenant, changeons la commande echo en quelque chose de plus utile - disons, la commande zip. À savoir, nous allons ajouter des fichiers dans une archive. Et, obtenons quelques arguments dans le mélange!
pour i dans $ @; faire
archive zip «$ i»
terminé
Il y a quelque chose de nouveau! “$ @” Est un raccourci pour “1 $ 2 $ 3 $… n $”. En d'autres termes, il s'agit de la liste complète de tous les arguments que vous avez spécifiés. Maintenant, regardez ce qui se passe lorsque je lance le script avec plusieurs fichiers d'entrée.
Vous pouvez voir quels fichiers sont dans mon dossier. J'ai exécuté la commande avec six arguments et chaque fichier a été ajouté à une archive compressée nommée «archive.zip». Facile, droit?
Les boucles sont plutôt magnifiques. Vous pouvez maintenant exécuter des fonctions de traitement par lots sur des listes de fichiers. Par exemple, vous pouvez copier tous les arguments de votre script dans une archive compressée, déplacer les originaux dans un autre dossier et copier automatiquement ce fichier zip sur un ordinateur distant. Si vous configurez des fichiers de clés avec SSH, vous n'aurez même pas besoin d'entrer votre mot de passe et vous pouvez même dire au script de supprimer le fichier zip après l'avoir téléchargé.!
L'utilisation de boucles for facilite la réalisation de nombreuses actions pour tous les fichiers d'un répertoire. Vous pouvez empiler une grande variété de commandes et utiliser des arguments très facilement pour créer une liste à la volée. Ce n’est que la partie visible de l’iceberg..
Scripteurs Bash, avez-vous des suggestions? Avez-vous créé un script utile utilisant des boucles? Voulez-vous partager vos réflexions sur la série? Laisser des commentaires et aider d'autres novices en script!