En utilisant zsh
, j'obtiens un message "Aucune correspondance trouvée" lorsque je choisis un modèle qui ne correspond pas à rm
et cela même lorsque je redirige la sortie.
# rm * > /dev/zero 2>&1
zsh: no matches found: *
Comment puis-je me débarrasser de ce message?
Ce comportement est contrôlé par Zsh nomatch
option . Par défaut, si une ligne de commande contient une expression de globalisation qui ne correspond à rien, Zsh affichera le message d'erreur que vous voyez et n'exécutera pas la commande du tout. Vous pouvez désactiver cela en exécutant
setopt +o nomatch
Ensuite, les expressions globales qui ne correspondent à rien seront laissées telles quelles et vous obtiendrez un message d'erreur de rm
(que vous pouvez désactiver à l'aide de -f
, bien que ce soit une mauvaise idée car cela forcera les suppressions dans d'autres situations où vous ne voudrez peut-être pas).
Que voudriez-vous qu'il fasse à la place? Ne pas exécuter rm
du tout (1)? L'exécuter avec un argument littéral *
Comme dans d'autres shells de type Bourne (2)? Exécutez-le sans argument du tout (3)?
files=(*(N)); (($#files)) && rm -- $files
. Ou (rm -- *) 2> /dev/null
Mais cela masquerait également les vraies erreurs par rm
ce qui serait idiot. Vous pouvez ignorer l'erreur zsh
mais restaurer stderr pour la commande rm
avec (rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
emulate sh -c 'rm -- *' 2> /dev/null
. Ensuite, comme dans sh
qui zsh
maintenant émulé pour cette seule ligne de commande, le *
Non correspondant est passé tel quel à rm
et rm
se plaint car ce fichier *
n'existe pas. Nous supprimons le stderr de rm
comme vous le feriez dans sh
pour supprimer ce message d'erreur, mais encore une fois, c'est idiot car cela cacherait les erreurs réelles par rm
par opposition à l'erreur encourue par la mauvaise conduite de sh
en passant un littéral *
à rm
. rm -f '*'
Ne se plaindrait pas d'un fichier *
Inexistant, vous pouvez donc faire emulate sh -c 'rm -f -- *'
rm -- *(N)
. rm
se plaindrait si aucun argument n'était passé, mais encore une fois, pas rm -f
: rm -f -- *(N)
.En règle générale, rm -f
Est la commande que vous souhaitez utiliser si vous souhaitez que tous les fichiers disparaissent et que vous obtenez une erreur uniquement si les fichiers n'ont pas pu être supprimés ou si l'IOW est toujours là après le retour de rm
. Vous souhaitez également généralement utiliser -f
Dans les scripts pour éviter que l'utilisateur ne soit invité dans certaines situations.
Ici, appeler rm
lorsque le glob ne correspond pas est incorrect. Le sh
1 le comportement est mauvais. C'est inoffensif pour un modèle comme *
, Mais pour un modèle comme *.[ch]
, Passer *.[ch]
Tel quel lorsqu'il ne correspond pas pourrait provoquer le fichier *.[ch]
à supprimer par erreur:
$ ls
*.[ch] foo.txt
$ zsh -c 'rm *.[ch]'
zsh:1: no matches found: *.[ch]
$ ls
*.[ch] foo.txt
$ sh -c 'rm *.[ch]'
$ ls
foo.txt
Un échec avec une erreur est la chose la plus raisonnable à faire et c'est ce que zsh
(et fish
, csh
, tcsh
, bash -o failglob
Et le shell Unix d'origine).
Et si vous voulez vous occuper de ce cas particulier, zsh
vous facilite la tâche avec son qualificatif glob (N)
(Pour noglob ) comme dans le cas (1) ci-dessus. fish
(au moins dans version récente ) le rend encore plus facile car il fait un noglob implicite pour le set
commande. Donc, l'équivalent là-bas serait:
set files *
if count $files > /dev/null
rm -f -- $files
end
Voir Pourquoi nullglob n'est pas par défaut pour plus de détails.
1. À proprement parler, ce n'est que sh
depuis le Bourne Shell (depuis Unix V7 en 1979); les versions antérieures de sh
(qui appelaient /etc/glob
sur des caractères génériques non cités, d'où vient le nom glob ) se comporter comme csh
ou zsh -o cshnullglob
, c'est-à-dire que /etc/glob
annulerait la commande si aucun des globes n'avait de correspondance (et supprimerait les globes non correspondants si au moins l'un des ils avaient n'importe quel match). Le comportement a été rompu par le Bourne Shell.