IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Déterminer la nature d'une commande au sein d'un script


Sujet :

Shell et commandes GNU

  1. #1
    Membre averti
    Homme Profil pro
    Chef de Projet MOE
    Inscrit en
    Janvier 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de Projet MOE
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2009
    Messages : 22
    Par défaut Déterminer la nature d'une commande au sein d'un script
    Bonjour à tous,

    Au sein d'un script shell (que je dois réaliser dans un cadre pédagogique), j'ai besoin, avant d'en lancer l'exécution en boucle sur des noms de fichier, de déterminer la nature d'une commande qui a été passée en paramètre du script.
    Cette commande, avec ses éventuelles paramètres, doit permettre de modifier les noms de fichier (par exemple 'tr a-z A-Z', pour mettre le noms en majuscule).
    Or, pour sécuriser a minima mon script, je souhaiterais prendre quelque précautions sur cette commande.

    J'ai pu tester si cette commande existait grâce à «which».
    Grace à «type», je peux savoir s'il s'agit d'une primitive du shell, d'une commande externe etc.
    Mais à ce stade, je ne sais pas comment faire pour m'assurer que cette commande va bien uniquement modifier des chaines de caractère (et donc réellement faire une modification de noms de fichier) et ne pas agir sur les fichiers (j'ai fait un test en lui passant 'rm' en paramètre, et aie ça marche ...)


    Je vous remercie d'avance pour toute aide que vous pourriez m'apporter.

  2. #2
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 346
    Par défaut
    Bonjour,

    Pour ma part, je ne connais pas de solution à ce problème, à part en créant à l'avance une liste de catégorie des commandes...

    Sinon, pourrait-on avoir plus de précisions sur le besoin d'un tel script ?
    Tu dis que c'est dans un but pédagogique, donc se serait pour que les commandes "dangereuses" ne soit pas executés ?
    Et si, on s'arrangeait pour qu'elles ne soit pas vu et accessible sans modifier les droits de ces commandes, mais en créant un type d'utilisateur qui ne peut avoir acces qu'à des commandes bien déterminées ?

  3. #3
    Membre averti
    Homme Profil pro
    Chef de Projet MOE
    Inscrit en
    Janvier 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de Projet MOE
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2009
    Messages : 22
    Par défaut
    Oui, c'est dans un cadre pédagogique : je suis une formation professionnelle et ce script et un sorte de mini-projet à rendre. Le but du formateur est de nous montrer comment réaliser quelque chose de véritablement propre, en tenant compte des erreurs éventuelles d'utilisation, des interruptions éventuelles, cas particulier etc.

    Je me suis aussi posé la question d'éventuellement créer une liste des commandes autorisées. Cette méthode à ses avantages mais peu manquer de souplesse et être moyennement portable dans les différents linux et unix. J'hésite.

    Citation Envoyé par disedorgue Voir le message
    Et si, on s'arrangeait pour qu'elles ne soit pas vu et accessible sans modifier les droits de ces commandes, mais en créant un type d'utilisateur qui ne peut avoir acces qu'à des commandes bien déterminées ?
    Heu, je ne suis pas certain de comprendre, mais cela ne reviendrait-il pas à lister les commandes autorisées avec ce script ?

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 115
    Billets dans le blog
    148
    Par défaut
    Bonjour,

    Pour faire de l'exécution de commande de manière sécurisée, alors que la commande est quelconque, moi, je mettrais en place un nouvel utilisateur avec des droits très limité et je me placerai dans un dossier /tmp/sandbox, avec aucun droit dessus.
    Avec un sudo / su cela marchera, car la commande en question sera exécuté en tant que cet utilisateur limité qui n'aura accès qu'au strict minimum. De plus, on peut même lui limiter les commandes à un sous ensemble défini.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Bonjour,

    As-tu essaye de jouer avec les droits ? Pour renommer un fichier, tu n'as pas besoin des droits d'ecriture, alors que pour le modifier si.

    Mais ca ne te permettra pas de savoir quel est le type de la commande passee.

    Ceci dit, je veux bien connaitre l'idee de ton prof, car je ne vois pas comment il pourra faire pour distinguer un mv d'un rm. D'autant plus que le mv ne fait pas la meme chose si le dossier de destination est sur la meme partition ou sur une autre : un mv au sein d'une meme partition "deplace" le fichier, alors qu'un mv entre 2 partitions copie le fichier puis supprime l'ancien (regardez l'inode, ca se voit bien).
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  6. #6
    Membre averti
    Homme Profil pro
    Chef de Projet MOE
    Inscrit en
    Janvier 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de Projet MOE
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2009
    Messages : 22
    Par défaut
    Je ne pense avoir le droit de créer un nouvel utilisateur : je dois rendre un script et rien d'autre. Certes, on peut créer des utilisateurs via un script; mais le but est de créer une nouvelle commande. Dans ce contexte, ajouter un utilisateur me parait une modification excessive de l'environnement ... quoi qu'on peut le supprimer à l'issu ? Je ne suis pas certain de réussir à maîtriser la chose (j'imagine qu'il faudrait un nom d'utilisateur aléatoire par exemple). À voir.

    Pour mieux situer ce que je dois faire, le sujet se trouve à cette adresse :
    http://www.ensta-paristech.fr/~joire...IN405-2013.pdf
    Sachant qu'il nous a demandé de «blinder» au maximum ce script (en capturant entre autre les interruptions éventuelles de l'utilisateur).

    (je ne souhaite pas pour l'instant avoir une solution toute faite, ce ne serait pas intéressant)

    D'où le fait que je me pose la question de le manière de filtrer les commandes passées en argument, en essayant de n'être ni trop permissif, ni trop rigide.

    PS : en même temps, j'avais mal fait mon script et il ne fonctionnait pas avec l'exemple du prof. Maintenant, ce cas nominal fonctionne et rm provoque une erreur. C'est déjà mieux lol

  7. #7
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Bonjour,

    Entre l'exercice dont tu donnes l'enonce et ce que tu dis ici, il y a un monde.

    D'un cote, le prof te demande de recoder rename, en lui passant la commande a executer sur les fichiers : c'est un exercice qui implique boucles et tests, et qui est faisable.

    De l'autre, tu parles de verifier que l'action demandee ne va pas modifier autre chose que le nom du fichier, ce qui est beaucoup plus complexe, d'autant plus complexe que certaines commandes ont un comportement different selon ce que tu leur demandes -- et c'est notamment le cas du deplacement des fichiers avec mv.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  8. #8
    Membre averti
    Homme Profil pro
    Chef de Projet MOE
    Inscrit en
    Janvier 2009
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de Projet MOE
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2009
    Messages : 22
    Par défaut
    Le truc c'est qu'il nous a clairement demandé de «blinder» nos scripts et qu'on sera essentiellement évalué là-dessus. Au final, voici ce que j'ai rendu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
     
    #!/bin/bash
     
    # Script du mini projet du cours IN405
    # Auteur : Marc DORIDANT
     
    # Ce script doit permettre de renommer une liste de fichiers
    # en appliquant une commande Unix passée en paramètre
    # pour transformer le nom d’origine de chaque fichier en un nouveau nom
     
    # Ce script comporte trois parties
    # Partie 1 : Positionnement des traps
    # Partie 2 : Déclarations des variables et des fonctions utiles aux traitements
    # Partie 3 : Corps du script consacré à l'analyse des paramètres (options et arguments) avant appel aux fonctions de traitements
     
    #####################################
    # Partie 1 : Positionnement des traps
    #####################################
    trap confirmer 2 3 # L'utilisateur devra confirmer avant de quitter (la fonction confirmer appelera aussi la fonction bilan)
    trap bilan 0 # Un bilan du nombre de fichier(s) traité(s) sera fourni avant de sortir
     
    ######################################
    # Partie 1 : Déclaration des variables
    ######################################
    # Variable relative au nombre de fichiers traités et au fait que le traitement a pu débuter
    # Tant qu'il vaut N, le véritable traitement des fichiers n'a pas débuté ou n'a pas pu débuter
    # S'il passe à 0, le traitement a débuté mais n'a pas encore traité de fichier
    nb=N # Par défaut, aucun fichier n'a été traité, et on n'a même pas débuté de traitement
    # Variable relative à l'activation du mode verbeux
    verbeux=N # Par défaut, le mode n'est pas activé (N pour No, Y pour Yes)
    # Variable relative à l'activation du mode interactif, où l'utilisateur doit confirmer pour chaque fichier
    confirmation=N # Par défaut, le mode n'est pas activé (N pour No, Y pour Yes)
    # Variable relative à l'activation du mode avec extension
    extension=N # Par défaut, le mode n'est pas activé (N pour No, Y pour Yes)
    # Variable relative au nom avec chemin absolu du script
    # Elle sera nécessaire pour s'interdire de se renommer soit-même
    myself=`readlink -f $(which "$0")`
     
    ######################################
    # Partie 3 : Déclaration des fonctions
    ######################################
    # Fonctions d'erreurs : appelée lorsqu'une erreur est détectée par le script
    # Elles envoient leurs messages sur la sortie d'erreur
    # Puis elles termine le script avec un code de retour selon le numéro d'erreur
    erreur1(){
    	echo "Erreur : rename nécessite des paramètres !" >&2
    	echo "Utilisez l'option -h pour afficher l'aide sur cette commande" >&2
    	exit 1
    }
    erreur2(){
    	echo "Erreur : option inconnue !" >&2
            echo "Utilisez l'option -h pour afficher l'aide sur cette commande" >&2
            exit 2
    }
    erreur3(){
            echo "Erreur : fonction non autorisée !" >&2
            echo "Utilisez l'option --allowed pour afficher la liste des fonctions autorisées" >&2
            exit 3
    }
    erreur4(){
            echo "Erreur : Aucun fichier à traiter !" >&2
    	echo "Rename nécessite des noms de fichier en paramètre" >&2
            echo "Utilisez l'option -h pour afficher l'aide sur cette commande" >&2
            exit 4
    }
    erreur5(){
    	echo "Erreur : Fonction autorisée mais commande invalide !" >&2
    	echo "Veuillez vous reporter au man de la commande utilisée" >&2
    	exit 5
    }
     
    # D'autres messages d'erreurs peuvent être générés, au sein du script
    # N'étant pas factorisable et ne provoquant pas de sortie du script, ils sont générés "sur place"
     
    # Fonction aide : appelée par l'option -h sur le script
    # Elle affiche l'aide pour utiliser la commande
    aide(){
    	echo "Usage rename.sh [-q] [-v] [-h] <commande> fichier ..."
    	echo "Renomme les fichiers en appliquant la commande sur les noms"
    	# Cette option a été ajoutée suite à des tests faisant apparaitre des comportements insatisfaisants
    	# En effet, faire un rev sur toto.txt qui génère un txt.otot n'était pas satisfaisant
    	# En revanche, l'utilisateur doit pouvoir utiliser sed ou tr pour modifier des extensions de fichier
    	echo "-e : extension, autorise la commande à agir sur l'extension du fichier"
    	echo "-q : query, demande confirmation pour chaque fichier"
    	echo "-v : verbeux, affiche ce qui est fait"
    	echo "--alowed : affiche la liste des commandes autorisées"
    	# L'option --help a été ajouté juste pour le plaisir de voir comment traiter des options longues
    	echo "-h -- help : affichage de ce message d'aide"
    	echo "Exemple :"
    	echo "rename.sh 'tr a-z A-Z' toto titi"
    	echo "renommera toto en TOTO et titi en TITI"
    	exit 0
    }
     
    # Fonction allowed : appelée par l'option -allowed sur le script
    # Cette fonction affiche la liste des commandes autorisées en paramètre de ce script
    # En effet, dans l'optique de sécuriser l'usage du script à sa capacité de renommer des fichiers
    # J'ai choisi de limiter les fonctions utilisables pour éviter tout détournement
    # Dans l'idéal, j'aurais souhaité catégoriser les commandes agissant sur des lignes de texte lues sur l'entrée standard
    # Je n'y suis pas parvenu j'ai donc recherché les commandes utilisables dans ce contexte
    # Cette liste peut facilement être étendue (voir les 15 dernières lignes du script)
    allowed(){
    	echo "Liste des commandes autorisées"
    	echo "tr"
    	echo "head -c (option obligatoire)"
    	echo "tail -c (option obligatoire)"
    	echo "rev"
    	echo "cut"
    	echo "sed"
    	exit 0
    }
     
    # Fonction confirmer : appelée si l'utilsateur tente de terminer le script pendant son exécution
    confirmer(){
    	echo "Voulez-vous vraiment intérompre l'exécution de rename ? (Y/N)"
    	# Lecture d'un seul caractère en tant que réponse
    	read -n 1 -s conf
    	# On ne confirme l'intéruption qu'avec Y ou y, tout autre caractère fait reprendre le traitement
    	if [ "$conf" = "Y" ] || [ "$conf" = "y" ] ; then
    		exit 0
    	fi
    	# On informe l'utilsateur de cette reprise
    	echo "Reprise"	
    }
     
    # Fonction bilan : appelée lors d'une sortie sans erreur de rename
    bilan(){
    	# Si nb est encore à N, c'est qu'on n'a rien fait (sortie via help ou allowed, ou avant même d'avoir validé la commande)
    	if test "$nb" != "N"; then
    		if [ $nb -eq 0 ]; then # On a commencé mais aucun fichier n'a été renommé
    			echo "Aucun fichier n'a été traité"
    		elif [ $nb -eq 1 ]; then # Un fichier renommé
    			echo "Un fichier a été renommé"
    		else # Plusieurs fichiers renommés (orthographe oblige !)
    			echo "$nb fichiers ont été renommés"
    		fi
    	fi
    }
     
    #####################################################################################################
    # Fonction renommer : réalise l'odre de renommer un fichier et gère le décompte des fichiers renommés
    #####################################################################################################
    # Cette fonction est l'ultime étape, à l'échelle d'un fichier, du traitement
     renommer(){
    	# Certaines vérifications préliminaires faites ici aurait pu être déléguées à la commande mv
    	# Mais afin de fiabliser le décompte des fichiers vraiment traités
    	# Et pour masquer l'implémentation à l'utilisateur (seul le script lui parle sauf mode verbeux)
    	# C'est le script que se charge en amont de ces vérifications et qui propose les solutions
    	# On vérifie si on ne va pas écraser un fichier existant
    	if test -f "$2"; then
    		# Si on a le droit d'écraser ce fichier
    		if test -w "$2"; then
    			# On propose d'écraser le fichier
    			echo "Le nouveau nom "${2##./}" du fichier "${1##./}" existe, voulez-vous écrasez l'actuel "${2##./}" ? (Y/N)"
    			# Lecture d'un seul caractère en tant que réponse
    			read -n 1 -s conf
    			# On ne confirme l'écrasement qu'avec Y ou y, tout autre caractère fait reprendre le traitement sans écraser le fichier
      			if [ "$conf" != "Y" ] && [ "$conf" != "y" ] ; then
    				return # On sort de la fonction
            		fi
    		else
    			# Note : mv proposerait d'outrepasser les droits quand c'est possible, pas ce script			
    			echo "Impossible de renommer "${1##./}" en "${2##./}", "${2##./}" existe et vous n'avez pas les droits pour l'écraser" >&2
    			return
    		fi
    	else
    		if test -e "$2"; then
    			echo "Impossible de renommer "${1##./}" en "${2##./}", "${2##./}" existe et n'est pas un fichier ordinaire" >&2
    			return
    		fi
    	fi
    	# C'est cette commande "ultime" qui réalise vraiment le taitement
    	$ordre "$1" "$2"
            # Si cette dernière commande s'est bien terminée
            if [ $? -eq 0 ]; then
            # On a traité un fichier de plus
            	nb=`expr $nb + 1`
            fi
    }
     
    #############################################################
    # Fonction traitement : réalise le traitement nominal attendu
    #############################################################
    # Cette fonction est appelée lorsque tous les contrôles des paramètres ont été effectués
    # Elle est le corps principal du traitement des fichiers, préparant le nécessaire pour l'appel de la fonction renommer
    traitement(){
    # La commande ayant été validée syntaxiquement
    # on considère que le vrai traitement a débuté
    # On peut donc commencer à compter les fichiers traités
    nb=0
    # Tant qu'il y a des noms de fichier à traiter
    while [ $# -gt 0 ]; do
    	if test -f "$1"; then
    		if test -w "$1"; then
    			# On s'interdit de se renommer soit même
    			# On détermine le nom avec chemin absolu du fichier à renommer
    			absNom=`readlink -f "$1"`
    			# On le compare avec celui du script rename.sh
    			if [ "$absNom" = "$myself" ]; then
    				echo "Il est interdit d'utiliser ce script sur lui même" >&2
    			else
    				# À ce stade, le fichier existe, est ordinaire, et l'on possède les droits pour le renommer
    				# Il faut cependant limiter cette action au nom de fichier, en écartant son chemin et son suffixe
    				# On sépare d'abord le nom complet du chemin
    				chem=`dirname "$1"`
    				nomComp=`basename "$1"`
    				if [ "$extension" = "Y" ]; then
    					name="$nomComp"
    					ext=""
    				else
    					# Puis on sépare le nom de l'extension
    					ext="${nomComp##*.}"
    					name="${nomComp%.*}"
    				fi
    				# Cas particulier : s'il s'agit d'un fichier sans extension, ext et name seront égaux
    				if test "$ext" = "$name"; then
    					# Si la recomposition ne redonne pas le nom complet du fichier
    					if test "$name"."$ext" != "$nomComp"; then
    						ext="" # C'est qu'il n'y a pas d'extension
    					fi
    				fi
    				# Si l'extension n'est pas vide, alors on prépare la recomposition du nom de fichier complet
    		                if test "$ext" != ""; then
    		                        ext=."$ext"
    		                fi
    				# On tente d'appliquer la fonction fournie sur ce nom de fichier pour fabriquer le nouveau
    				newName=`echo "$name" | eval "$commande"`
    				# Si la dernière commande ne s'est pas bien terminée
    				if [ $? -ne 0 ]; then
    					erreur5 # C'est que l'utilisateur a mal formulé sa commande, on sort avec une erreur 5 
    				fi
    				# Avant de renommer le fichier, il faut s'assurer que ce nouveau nom est valable et utile
    				# Il faut que $newName ne soit ni vide, ni ".", ni "..", ni identique à l'ancien nom
    				# Il faut aussi qu'il ne contienne aucun caractère interdit ( "/" et "\0" )
    				# On pourrait aussi proscrire d'autres caractères fortement déconseillés comme le retour à la ligne
    				# Il semblerait après plusieurs tests que "\0" ne pose aucun soucis mais il reste filté par prudence
    				if [ "$name" = "$newName" ]; then
    					# Ce message n'est pas considéré comme un message d'erreur, il s'agit d'une information
    					# Il est donc laissé sur la sortie standard
    					echo "Aucun changement pour "${1##./}", le nouveau nom est identique à l'ancien"
    				else	
    					if [ -z "$newName" ] || [ "$newName" = "." ] || [ "$newName" = ".." ] || [[ "$newName" == */* ]] || [[ "$newName" == *\0* ]]; then
    						echo "Aucun changement pour "${1##./}", le nouveau nom est vide ou interdit" >&2
    					else
    						# On recompose le nom complet du fichier
    						newName="$chem"/"$newName""$ext"
    						# On vérfie maintenant si le script ne se cible pas lui-même
    						absNom=`readlink -f "$newName"`
    						# On le compare avec celui du script rename.sh
    						if [ "$absNom" = "$myself" ]; then
    							echo "Aucun changement pour "${1##./}", le nouveau nom est interdit" >&2
    						else
    							# Si on est en mode confirmation
    							if [ "$confirmation" = "Y" ] ; then
    								# On montre la sitation à l'utilisateur pour avis
    								echo "Voulez-vous renommmer $1 en $new ? (Y/N)"
    								# Réponse en 1 caractère, masqué, sans apuyer sur entrée
    								read -n 1 -s rep
    								# Y validera le changement de nom, tout autre réponse non
    								if [ "$rep" = "Y" ] || [ "$rep" = "y" ] ; then
    									renommer "$1" "$newName"
    								fi
    							else
    								# Commande exécutée sans confirmation
    								renommer "$1" "$newName"
    							fi
    						fi
    					fi
    				fi
    			fi
    		else
    			echo "Erreur : Vous n'avez pas les droits requis pour renommer "${1##./}"" >&2
    		fi
    	else
    		echo "Erreur : "${1##./}" n'existe pas ou n'est pas un fichier ordinaire" >&2
    	fi
    	shift
    done
    }
     
    # Partie 2 : Corps du script consacré à l'analyse des options et arguments passés en paramètres
    # S'il n'y a aucun paramètres, on appelle la fonction d'erreur
    [[ $# -lt 1 ]] && erreur1
     
    # Analyse des options à l'aide de la fonction getopt
    # Les options invalides seront ignorées
    # Les options peuvent avoir été mélangées dans les paramètres, elles seront prises en compte
    options=$(getopt -o q,v,h,e -l help,allowed -- "$@" 2>/dev/null)
     
    # éclatement de $options en $1, $2...
    eval set -- $options
     
    while true; do
        case "$1" in
            -q) confirmation=Y # On mémorise que le mode confirmation est actif
                shift;; # On décale la liste des options de 1
    	-v) verbeux=Y # On mémorise que le mode verbeux est actif
    	    shift;; # On décale la liste des options de 1
    	-e) extension=Y # On inclu l'extension dans la partie à renommer
    	    shift;; # On décale la liste des options de 1
            -h|--help) aide # On lance la fonction d'affichage de l'aide, la présence de cette option inhibe tout traitement
                shift;; # On décale la liste des options de 1
    	--allowed) allowed # On lance l'affichage des fonctions autorisées, la présence de cette option inhibe tout taitement
    	    shift;;
            --) # fin des options
                shift # On décale la liste des options de 1
                break;; # On est prêt pour passer au traitement
            *) erreur2;; # Au cas où quelque chose passerait au travers de getopt, on sort avec une erreur 2
        esac
    done
     
    # Analyse du premier argument : la commande
    # On commance par récupérer la commande passé en argument dans la variable commande
    commande="$1"
    shift # On décale la liste des options de 1, il ne doit rester que les noms de fichier à traiter
    # Il faut s'assurer que la commande et ses paramètres sont valides et non dangereux
    # Cette validation repose une liste de commandes autorisées (avec éventuellement une option obligatoire)
    # Liste des commandes actuellement autorisées : voir fonction allowed
    # Pour savoir si la commande correspond à l'une de ses commandes autorisées, on test si la chaine correspond à l'un des motifs
    # On chaine ces tests de tels sorte que si rien ne match, le code de retour final ne sera pas 0
    expr match "$commande" '^tr ' >&/dev/null || expr match "$commande" '^head -c ' >&/dev/null || expr match "$commande" '^tail -c ' >&/dev/null || expr match "$commande" '^rev$' >&/dev/null || expr match "$commande" '^cut ' >&/dev/null || expr match "$commande" '^sed ' >&/dev/null
    # Si le code de retour de la chaine de commande précendent vaut 0, c'est que la commande passée n'est pas autorisée
    if [ $? -ne 0 ]; then
    	erreur3 # Donc on sort avec une erreur 3
    fi
    # Note : Pour étendre l'usage du script, il suffit donc d'ajouter un test dans la chaine
    # Il ne faut pas oublier de mettre à jour la fonction allowed en conséquence
     
    # Vérification sommaire sur les noms de fichier
    # S'il n'y a pas d'autre paramètre, c'est qu'aucun nom de fichier n'a été saisi
    if [ $# -eq 0 ]; then
            erreur4 # Donc on sort avec une erreur 4
    fi
    # Les vérifications plus poussées se feront en durant le traitement
     
    # On prépare la commande, à base de commande mv
    if [ "$verbeux" = "Y" ]; then # Si le mode verbeur a été demandé
    	ordre="mv -v" # On s'appuie sur le mode verbeux de la commande mv (dans une version précédente, on utilisait mv -v -i)
    else
    	ordre="mv" # On garde la commande mv de base (dans une version précedente, on utilisait mv -i)
    fi
     
    # On peut maitenant lancer la fonction de traitement
    traitement "$@"
    J'espère que je n'ai pas été trop mauvais.
    Je vais considérer le problème comme résolu même si je l'ai contourné.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Déterminer la nature exacte d'une ligne ambiguë
    Par Snack3r dans le forum Débuter
    Réponses: 2
    Dernier message: 15/10/2013, 01h25
  2. Impossible d'exécuter une commande avec su dans un script bash
    Par koshieDotFr dans le forum Shell et commandes GNU
    Réponses: 8
    Dernier message: 18/12/2012, 13h47
  3. Lancer une commande avec pipes depuis un script
    Par theclem35 dans le forum Shell et commandes POSIX
    Réponses: 2
    Dernier message: 08/02/2012, 20h41
  4. Limiter la portée d'une commande \ifthenelse et d'un compteur au sein d'une boite
    Par Théodulf dans le forum Programmation (La)TeX avancée
    Réponses: 7
    Dernier message: 18/04/2011, 23h11
  5. Déterminer l'adresse d'une application en mémoire
    Par Gib dans le forum x86 32-bits / 64-bits
    Réponses: 9
    Dernier message: 11/06/2002, 14h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo