Pas besoin de faire des tours de passe-passe :
for i in *.java; do
[ -f "$i" ] || break
...
done
La garde garantit que s'il n'y a pas de fichier correspondant, la boucle se terminera sans essayer de traiter un nom de fichier inexistant. *.java
.
Sur bash
(ou des shells supportant quelque chose de similaire), vous pouvez utiliser la fonction nullglob
option pour simplement ignorer une correspondance ratée et ne pas entrer dans le corps de la boucle.
shopt -s nullglob
for i in *.java; do
...
done
Quelques détails supplémentaires sur le break
-vs- continue
discussion dans les commentaires. Je considère qu'il est quelque peu hors de propos de savoir si vous utilisez break
ou continue
parce que la première boucle essaie de faire la distinction entre deux cas :
-
*.java
n'a pas de correspondance, et est donc traité comme du texte littéral.
-
*.java
avait au moins une correspondance, et cette correspondance pouvait inclure une entrée nommée *.java
.
Dans le cas n°1, break
est bien, car il n'y a pas d'autres valeurs de $i
à venir, et break
et continue
serait équivalent (bien que je trouve break
plus explicite ; vous sortez de la boucle, vous ne vous contentez pas d'attendre que la boucle se termine passivement).
Dans le cas n° 2, vous devez encore effectuer le filtrage nécessaire sur toutes les correspondances possibles. En tant que tel, le choix de break
ou continue
est moins important que celui qui test ( -f
, -d
, -e
etc.) vous vous adressez à $i
Ce qui, selon moi, n'est pas la bonne façon de déterminer si vous êtes entré dans la boucle "incorrectement" en premier lieu.
C'est-à-dire que je ne veux pas être dans la position d'examiner la valeur de $i
du tout dans le cas n°1, et dans le cas n°2, ce que vous faites avec la valeur a plus à voir avec votre logique d'entreprise pour chaque fichier, plutôt qu'avec la logique de la fonction en sélectionnant les fichiers à traiter en premier lieu. Je préfère laisser cette logique à l'utilisateur individuel, plutôt que d'exprimer un choix ou l'autre dans la question.
En passant, zsh
permet d'effectuer ce type de filtrage dans le glob lui-même. Vous pouvez faire correspondre seulement les fichiers réguliers se terminant par .java
(et désactiver le comportement par défaut qui consiste à traiter les motifs non appariés comme une erreur, plutôt que comme du texte littéral) à l'aide de la commande
for f in *.java(.N); do
...
done
Avec ce qui précède, vous êtes garanti que si vous atteignez le corps de la boucle, alors $f
se développe vers le nom d'un fichier ordinaire. Le site .
fait *.java
ne correspondent qu'aux fichiers réguliers, et l'option N
fait en sorte qu'une correspondance échouée ne se développe pas au lieu de produire une erreur.
Il existe également d'autres qualificatifs globaux pour effectuer toutes sortes de filtrages sur les expansions de noms de fichiers. (J'aime plaisanter en disant que zsh
L'expansion des globes remplace la nécessité d'utiliser la fonction find
du tout).