Pourquoi le script suivant ne s'exécuterait-il pas, mais donnerait une erreur de syntaxe de else
:
LOGS3_DIR=~/logs
if [ -d "$LOGS3_DIR" ]; then
cd
cd "$LOGS3_DIR"
echo "$LOGS3_DIR"
for filename in `find "." -mtime 1 -type f`
do
if lsof "$filename" > /dev/null
then
# file is open
else
echo "deleting $filename"
rm "$filename"
fi
done
fi
N'utilisez pas de substitution de commande sur la sortie de find
. Ici, tout peut être fait avec find
:
find . -mtime 1 -type f ! -exec lsof -t {} \; -exec rm -f {} \; > /dev/null
Avec quelques implémentations find
(y compris FreeBSD find
d'où il vient et GNU find
), vous pouvez utiliser -delete
au lieu de -exec rm...
.
La raison pour laquelle vous obtenez une erreur est qu'il n'y a pas de commande entre then
et else
et certains shells (à commencer par le Bourne Shell d'où vient cette syntaxe) en nécessitent au moins un (et un commentaire n'est pas une commande). Notez que c'est complètement arbitraire et il n'y a aucune raison pour que ces obus fassent cela. yash
et zsh
n'ont pas cette limitation (if false; then else echo x; fi
et même if false; then else fi
fonctionnent bien avec eux).
Comme d'autres l'ont dit, vous pouvez utiliser une commande noop comme :
(Ou for nothing in; do nothing; done
) Ou inverser la logique avec le mot clé !
(Disponible dans les shells POSIX, mais pas le Bourne Shell (vous constaterez que l'utilisation de :
Pour cela était courante dans ce Shell)). mksh
et yash
arrivent à supporter if false; then () else echo x; fi
(je ne compterais pas dessus car cela pourrait changer dans les futures versions).
Une autre approche consiste à:
lsof... || {
cmd1
cmd2
}
bien qu'une différence soit le statut de sortie global qui sera celui de lsof
si lsof
échoue.
Il semble que vous souhaitiez faire un no-op si le fichier est ouvert, vous devez donc ajouter un :
, qui est une commande nulle dans bash
:
if lsof "$filename" > /dev/null; then
# file is open
:
else
printf 'deleting %s\n' "$filename"
rm -- "$filename"
fi
Si vous n'utilisez pas :
, bash
ne peut pas analyser votre code et affichera une erreur comme bash: syntax error near unexpected token 'else'
.
Une autre alternative: inversez votre logique.
if ! lsof "$filename" >/dev/null;then
echo "deleting $filename"
rm "$filename"
fi
Aucune des autres réponses ne répond réellement à votre question initiale de savoir pourquoi la commande donne une erreur de syntaxe. Cela est dû à une commande manquante entre puis et else .
Votre code d'origine ressemble à ceci:
if lsof "$filename" > /dev/null
then
# file is open
else
echo "deleting $filename"
rm "$filename"
fi
Le problème est que vous avez un commentaire entre puis et else , mais le commentaire n'est pas traité comme une commande. En bref, vous pouvez réécrire le problème que vous avez (structurellement parlant) comme suit:
$ if true; then else echo; fi
bash: syntax error near unexpected token `else'
Vous pouvez résoudre ce problème en plaçant les commandes réelles avant autrement , mais un commentaire en lui-même ne fera pas l'affaire. La section if-then ne peut pas être vide; si vous voulez un espace réservé, vous pouvez utiliser le colon intégré . Par exemple:
$ if true; then :; else echo; fi
Placer simplement :
dans la section entre puis et sinon corrigera l'erreur de syntaxe vous vivez.