Il y a quelques les choses ne vont pas avec votre script. Certains sont sérieux, d'autres moins.
Tout d'abord, les problèmes graves. Comme le suggère le gourou, vous devez utiliser des crochets pour entourer la condition if
. En effet, if
ne teste que la sortie d'une condition, il n'effectue pas de comparaison de chaînes réelles. Traditionnellement, un programme appelé /bin/test
, également appelé /bin/[
, prenait soin de cela. Ces jours-ci, cette fonctionnalité est intégrée au shell, mais /bin/sh
se comporte toujours comme s'il s'agissait d'un programme distinct.
En fait, vous pouvez faire des choses intéressantes avec if
lorsque vous ne pas utiliser des crochets pour votre condition. Par exemple, if grep -q 'RE' /path/to/file; then
est assez commun. La commande grep -q
ne génère aucune sortie, mais renvoie simplement un "succès" ou un "échec" détecté par if
.
Le deuxième problème sérieux est que vous faites écho à un état qui peut ou peut ne pas être vrai. J'appelle cela un sérieux problème parce que ... eh bien, les messages de journal ne devraient tout simplement pas faire de fausses déclarations. Si les autorisations sont incorrectes pour le fichier $1
ou si le nom de fichier contient un espace, votre commande mv
échouera, mais le message indiquera que ce n'est pas le cas. Plus à ce sujet plus tard.
Ensuite, les problèmes les moins graves.
Ce sont principalement des choses de style et d'optimisation.
Tout d'abord, read
sur la plupart des plates-formes inclut une option -p
qui vous permet de spécifier une invite. Utilisez ceci, et vous n'avez pas besoin d'inclure une commande echo
. Deuxièmement, l'indentation rend difficile la visualisation de la structure de la construction if
. Ce n'est pas un énorme problème dans un programme aussi petit, mais au fur et à mesure que vous grandissez, vous voulez VRAIMENT suivre des normes cohérentes. Troisièmement, vous pouvez probablement obtenir plus de flexibilité dans les questions à choix multiple comme ceci si vous utilisez les instructions case
au lieu de if
.
Après tout cela, voici comment j'écrire ce script:
#!/bin/sh
if [ "$1" = "-y" ]; then
ans=y
shift
elif [ -t 0 ]; then
read -p "Are you sure you want to delete '$1' (y/N) ? " ans
fi
case "$ans" in
Y*|y*)
retval=0
if [ -z "$1" ]; then
retval=64
echo "ERROR: you didn't specify a filename." >&2
if [ ! -f "$1" ]; then
retval=66
echo "ERROR: file '$1' not found!" >&2
elif mv "$1" /home/parallels/dustbin/; then
echo "File '$1' has been deleted" >&2
else
retval=$?
echo "ERROR: file '$1' could not be deleted!" >&2
fi
;;
*)
echo "ABORT: file '$1' has not been deleted" >&2
retval=4
;;
esac
exit $retval
En dehors de ce qui est mentionné ci-dessus, voici quelques choses dans ce bout de code:
[ "$1" = "-y" ]
- si l'utilisateur spécifie une option -y
, puis nous nous comportons comme si la réponse à la question était "oui".
[ -t 0 ]
- ceci teste si nous sommes sur un terminal interactif. Si nous sommes, alors il est logique de poser des questions avec read
.
Y*|y*)
- dans une instruction case, ceci correspond à toute chaîne commençant par un "y" majuscule ou minuscule. Les réponses affirmatives valides seraient donc "Y", "oui", "jaune", etc.
[ ! -f "$1" ]
- ceci teste si le fichier existe. Vous pouvez man test
ou man sh
pour voir les différents tests disponibles dans shell. (-f
peut ne pas être le plus approprié pour vous.)
>&2
- à la fin d'une ligne, envoie sa sortie à "erreur standard" au lieu de "sortie standard". Cela change la façon dont la sortie sera traitée par les canaux, cron, etc. Les erreurs et les données du journal sont souvent envoyées à stderr, de sorte que stdout peut être dédié à la sortie réelle d'un programme.
mv "$1" ...
- Le nom de fichier est entre guillemets. Cela vous protège au cas où le nom de fichier contient des caractères spéciaux comme des espaces.
$retval
- les valeurs pour cela provenaient d'une meilleure estimation de l'article le plus proche en man sysexits
.
retval=$?
- il s'agit du statut de sortie de la dernière commande exécutée. Dans ce cas, cela signifie que nous attribuons l'état de sortie mv
à la variable $retval
, de sorte que si mv
a échoué, le script entier indique la raison de l'échec, en ce qui concerne mv
.
Merci pour la réponse rapide et utile! –
Vous êtes les bienvenus ... Si la solution a fonctionné pour vous, acceptez la réponse. Si plusieurs réponses vous conviennent, acceptez celle qui correspond le mieux à votre problème ... – Guru