116 votes

Validation des paramètres dans un script bash

Je suis un débutant total à faire toutes les scripts bash, mais je suis venu avec une base pour aider à automatiser le processus de suppression d'un certain nombre de dossiers comme ils deviennent inutiles.

#!/bin/bash
rm -rf ~/myfolder1/$1/anotherfolder
rm -rf ~/myfolder2/$1/yetanotherfolder
rm -rf ~/myfolder3/$1/thisisafolder

C'est évoquée comme suit:

./myscript.sh <{id-number}>

Le problème est que si vous oubliez de taper dans l' id-number (comme je l'ai fait juste à l'époque), alors qu'il pourrait supprimer beaucoup de choses que vous ne voulez vraiment pas supprimé.

Est-il un moyen que vous pouvez ajouter n'importe quel formulaire de validation pour les paramètres de ligne de commande? Dans mon cas, il serait bon de vérifier que: a) il n'y a qu'un seul paramètre, b) il est numérique, et c) que le dossier existe; avant de poursuivre avec le script.

179voto

Brian Campbell Points 101107
#!/bin/sh
die () {
    echo >&2 "$@"
    exit 1
}

[ "$#" -eq 1 ] || die "1 argument required, $# provided"
echo $1 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $1 provided"

while read dir 
do
    [ -d "$dir" ] || die "Directory $dir does not exist"
    rm -rf "$dir"
done <<EOF
~/myfolder1/$1/anotherfolder 
~/myfolder2/$1/yetanotherfolder 
~/myfolder3/$1/thisisafolder
EOF

edit: j'ai raté la partie sur la façon de vérifier si les répertoires existent d'abord, alors j'ai ajouté que, en remplissant le script. Aussi, ont abordé des questions soulevées dans les commentaires; correction de l'expression régulière, ont changé de == de eq.

Ce doit être un portable, compatible POSIX script pour autant que je peux dire; elle ne bashisms, ce qui est réellement important, car /bin/sh sur Ubuntu est en fait dash ces jours-ci, pas bash.

24voto

Boiler Bill Points 1046

Pas aussi résistant que la réponse ci-dessus, mais toujours efficace:

 #!/bin/bash
if [ "$1" = "" ]
then
  echo "Usage: $0 <id number to be cleaned up>"
  exit
fi

# rm commands go here
 

22voto

lhunath Points 27045

L' sh de la solution, en Brian Campbell, tandis que les nobles et bien exécuté, a quelques problèmes, donc je pensais que je fournir mes propres bash de la solution.

Les problèmes avec l' sh d'un:

  • Le tilde en ~/foo ne s'étend pas à votre homedirectory à l'intérieur de heredocs. Et ni quand il est lu par l' read déclaration ou cité dans l' rm déclaration. Ce qui signifie que vous obtiendrez No such file or directory d'erreurs.
  • Bifurquer off grep et pour les opérations de base, c'est idiot. Surtout quand vous êtes avec un minable shell pour éviter le "lourd" poids de bash.
  • J'ai aussi remarqué quelques citant des questions, par exemple autour d'un paramètre d'expansion dans sa echo.
  • Bien que rares, la solution ne peut pas faire face avec des noms de fichiers qui contiennent des retours à la ligne. (Presque pas de solution en sh peut faire face avec eux - c'est pourquoi j'ai presque toujours préférer bash, il est beaucoup plus à l'épreuve des balles et plus difficile à exploiter, lorsque bien utilisé).

Alors, oui, à l'aide de /bin/sh pour votre hashbang signifie que vous devez éviter bashsmsi à tous les frais, vous pouvez utiliser tous les bashisms vous voulez, même sur Ubunutu ou autres joyeusetés lorsque vous êtes honnête et mettre #!/bin/bash en haut.

Donc, voici un bash solution qui est plus petit, plus propre, plus transparente, plus probablement "plus vite", et plus l'épreuve des balles.

[[ -d $1 && $1 != *[^0-9]* ]] || { echo "Invalid input." >&2; exit 1; }
rm -rf ~/foo/"$1"/bar ...
  1. Remarquez les guillemets autour de $1 dans la rm !
  2. L' -d vérification échoue également si $1 est vide, de sorte que les deux contrôles.
  3. J'ai évité les expressions régulières pour une raison. Si vous devez utiliser =~ de bash, vous devriez être en mettre à l'expression régulière dans une variable. Dans tous les cas, les globules comme le mien sont toujours préférables et pris en charge dans beaucoup plus de versions de bash.

16voto

Je voudrais utiliser bash [[ :

 if [[ ! ("$#" == 1 && $1 =~ ^[0-9]+$ && -d $1) ]]; then 
    echo 'Please pass a number that corresponds to a directory'
    exit 1
fi
 

J'ai trouvé cette faq être une bonne source d'informations.

8voto

guns Points 3881

Utilisez '-z' pour tester les chaînes vides et '-d pour rechercher les répertoires.

 if [[ -z "$@" ]]; then
    echo >&2 "You must supply an argument!"
    exit 1
elif [[ ! -d "$@" ]]; then
    echo >&2 "$@ is not a valid directory!"
    exit 1
fi
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X