Bash script: options dans une fonction

Tags: #<Tag:0x00007f63e60295d0>

Bonjour,

voici réduite au minimum, la structure d’un script de sauvegarde.
Le script fonctionne dans l’état où je vous le présente, mais à condition que le choix des options ne soit pas dans une fonction.
Est-ce une erreur dans la structure de ce script, ou mon ambition n’est-elle pas adaptée à bash? (version 5)

Merci pour votre attention

#!/bin/bash --
#set -eu #o pipefail
MONHOME(){
}

# Configuration:
readonly EXCLUS="/usr/local/etc/excludeRsyncSeagate4t-bkp.txt"
readonly DevSeagate='/dev/mapper/seagateUSB4T-bkp'
# Si nécessaire, point de montage par ce script:
PTMONTAGE="/mnt/Seagate4T-bkp" 
# Source = tout (système inclu)
SOURCE="/"

# Variables de travail
readonly CeScript=$(basename "$0")
DATE=$(date +%F_%s | cut -b 1-11,17-21)

CONNEXION() {
# est-il connecté?
}

MONTER() {
# Découvrir ou creer le point de montage
# Options par défaults:
USBDIR="$MONTE"

INFOS() {
exit 0
}
 
SYNTAXE() {
    MESSAGE "Syntaxe de $CeScript"
    echo
    echo "$CeScript [options]"
    echo
    MESSAGE "Options:"
    echo "-d    dry-run"
    echo "-o    <liste> autres options de rsync"
    echo "-i    infos sur ce script"
    echo "-h    cet écran d'aide"
    exit 0
}

#--#OPTIONS() {   # BUG: ça ne marche pas dans une fonction
# GESTION DES OPTIONS:
while getopts diho: option
do
  case "$option" in
          d ) OPTION='--dry-run'
                  ;;
          o ) OPTION="${OPTION} $OPTARG"
                  ;;
          i ) INFOS ; exit 0
                  ;;
          h ) SYNTAXE
              exit 0
                  ;;
          * ) MESSAGE "OPTION $OPTION non valide"
              exit 1
  esac
done
shift $((OPTIND-1))
#--#}

RSYNC() {
### Construction de la commande rsync:
DESTINATION="$MONTE"
time sudo rsync -auHAXCvv "$OPTION" --stats --exclude-from="$EXCLUS" "$SOURCE" "$DESTINATION"
}

DEMONTER() {
}

### Lancement du programme:
MONHOME     # racine des données partagées selon le système 
CONNECTION  # vérifie que le disque USB est connecté
MONTER      # vérifie que le disque USB monté, sinon le monte
#--#OPTIONS
RSYNC       # lancement de commande rsync, construite notamment en fonction des options
DEMONTER    # Demande avant de démonter le disque USB.

Bonjour,

Effectivement, en bash, les arguments d’une fonction utilisent les mêmes variables que les arguments de la commande.
Tu peux probablement passer les arguments de la commande directement à une fonction en appelant la fonction avec la variable $* en paramètre, ça fonctionne à condition que les arguments de ta commande ne comporte pas d’espace en dehors de la séparation des arguments entre eux.

ça fonctionne à condition que les arguments de ta commande ne comporte pas d’espace en dehors de la séparation des arguments entre eux.

C’est-à-dire que:
script_rsync -abcd
prendra en compte les options a,b,c et d

et
script _rsync -ab -c -d

ne prendra en compte que les options a et b (ou/et renverra une erreur) ?

Merci Almtesh

Bonjour,

dans une fonction, tu peux mettre tes variables localement à ta fonction par le mot local.
Tu peu ainsi avoir:

var01="toto" # ma variable est globale

function mafonction {
    local varlocal01="128"

    var01=`echo $var01"="$varlocal01`
}

echo mafonction $var01

Ce n’est qu’un exemple vite fait.

Merci Zargos,
cependant, je ne vois pas comment localiser la fonction peut résoudre ma question.

À partir de vos lumières, je ferai des essais dés que je pourrai m’y remettre.

En fait, je pense plutôt à un exemple du style :

script_rsync -abc '/home/almtesh/Mes Documents'

Là, le script est script_rsync, la première option est -abc, et la seconde est /home/almtesh/Mes Documents, si tu envoies ça à une fonction en utilisant la variable $*, tu obtiendras -abc en première option, /home/almtesh/Mes en deuxième option et Documents en troisième option à cause de l’espace dans la seconde option.
C’est typiquement le genre de problème que tu peux rencontrer. Si tu as déjà lancé scp pour transférer des fichiers distants qui comportent des espaces, tu dois très bien comprendre de quoi je parle.

En fait, le but ici est d’utiliser la variable pas locale pour récupérer les options de lancement du script et non celles de la fonction elle-même. Un peu genre :

function parse_args () {
	global $1
	
	if [ x"$1" = "x-r" ];then
		recursive=1
	else
		recursive=0
	fi

parse_args
if [ $recursive -eq 1 ];then
	echo "Récursif"
else
	echo "Pas récursif"
fi

Je n’ai pas testé, mais je pense que c’est ça le concept…

les arguments sont :
$0 => nom du script
$1…$xx => chacun des paramètres

Donc :

script _rsync -ab -c -d
c’est:
$0 = script_rsync
$1= -ab
$2=-c
$3=-d

Bonjour,

je n’ai pas tout compris au problème que tu as avec le parsing des options, mais si jamais getopts (la fonction builtin du shell) te pose problème, essaie getopt (sans s), qui est fourni avec le paquet util-linux, ça fait longtemps que je ne m’en suis pas servi, mais de mémoire il est plus souple que getopts, et permet notamment de parser des options au format long (comme --paramètre valeur)

La page man de getopt

Bonjour,
merci à tous.
Si j’ai bien lu, le plus simple est de renoncer à mettre getopts dans une fonction. Le mieux semble dans ce cas l’ennemi du bien!