En utilisant zsh
, j'obtiens un message "Aucune correspondance trouvée" lorsque je choisis un modèle qui ne convient pas rm
et cela même lors de la redirection de la sortie.
# rm * > /dev/zero 2>&1
zsh: no matches found: *
Comment puis-je me débarrasser de ce message?
setopt extended_glob
(ou même simplementrm * >/dev/null 2>&1
) mais vraiment vous devriez faire une solution de contournement pour ne pas avoir besoinrm *
, c'est carrément dangereux/dev/null
plutôtdev/zero
. De plus, votre redirection stderr manque un&
; ça devrait l'être2>&1
.zsh
pendant l'évaluation de la commande et non pendant l'exécution de la commande elle-même (en raison de l'erreur, la commande n'est même pas exécutée). Les redirections de sortie ici affectent uniquement la sortie de la commande et non le shell lui-même.Réponses:
Ce comportement est contrôlé par l'
nomatch
option de Zsh . 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écutantEnsuite, les expressions globales qui ne correspondent à rien seront laissées telles quelles, et vous obtiendrez un message d'erreur
rm
(que vous pouvez désactiver en utilisant-f
, bien que ce soit une mauvaise idée car cela forcera les suppressions dans d'autres situations où vous pourriez ne pas vouloir).la source
nullglob
etcshnullglob
. Sinullglob
est défini et qu'aucun fichier correspondant n'est trouvé, le modèle est supprimé de la liste des arguments au lieu de générer une erreur. Le réglagecshnullglob
a un effet similaire sauf si tous les modèles d'une commande n'ont aucune correspondance, auquel cas une erreur sera signalée. Remarque: réglagenullglob
oucshnullglob
remplacementsnomatch
. Vous pouvez également définirnullglob
des modèles simples en utilisant le qualificatif de globN
:rm *(N)
.nomatch
est loin d'être idéal, c'est ce que font les obus de type Bourne. Si le motif ne correspond pas, il est transmis tel quel àrm
(!) Ce quirm
donnera une erreur, ou pire pourrait supprimer le mauvais fichier pour un motif comme*.[ch]
par exemple!Que voudriez-vous qu'il fasse à la place? Pas exécuté
rm
du tout (1)? L'exécuter avec un*
argument littéral comme dans d'autres coquilles de type Bourne (2)? Exécutez-le sans argument du tout (3)?files=(*(N)); (($#files)) && rm -- $files
. Ou,(rm -- *) 2> /dev/null
mais cela cacherait également de véritables erreursrm
qui seraient idiotes. Vous pouvez ignorer l'zsh
erreur mais restaurer stderr pour larm
commande avec(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
emulate sh -c 'rm -- *' 2> /dev/null
. Ensuite, comme dans celuish
qui estzsh
maintenant émulé pour cette seule ligne de commande, la non-correspondance*
est transmise telle quellerm
et serm
plaint car ce*
fichier n'existe pas. Nousrm
supprimons le stderr de comme vous le feriezsh
pour supprimer ce message d'erreur, mais encore une fois, c'est idiot car cela cacherait de véritables erreurs parrm
opposition à l'erreur encourue par la mauvaise conduite desh
passer un littéral*
àrm
.rm -f '*'
ne se plaindrait pas d'un*
fichier inexistant, donc vous pouvez le faireemulate sh -c 'rm -f -- *'
rm -- *(N)
.rm
se plaindrait que lorsqu'ils ne sont pas passé aucun argument, mais encore une fois, nonrm -f
:rm -f -- *(N)
.Généralement,
rm -f
c'est la commande que vous souhaitez utiliser si vous voulez que tous les fichiers disparaissent et que vous obtenez une erreur uniquement si les fichiers n'ont pas pu être supprimés ou si IOW est toujours là aprèsrm
son retour. 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 faux. Le comportementsh
1 est incorrect. C'est inoffensif pour un modèle comme*
, mais pour un comme*.[ch]
, le passage*.[ch]
tel quel lorsqu'il ne correspond pas pourrait entraîner la*.[ch]
suppression du fichier par erreur:A défaut d'une erreur est la chose la plus sensée à faire et est ce que
zsh
(etfish
,csh
,tcsh
,bash -o failglob
et le shell Unix d' origine) fait.Et si vous voulez vous occuper de ce cas spécial,
zsh
c'est facile avec son(N)
qualificatif glob (pour noglob ) comme dans le cas (1) ci-dessus.fish
(au moins dans la version récente ) le rend encore plus facile car il fait un noglob implicite pour laset
commande. Donc, l'équivalent là-bas serait:Voir Pourquoi nullglob n'est-il pas par défaut pour plus de détails.
1 . À proprement parler, ce n'est que
sh
depuis le shell Bourne (depuis Unix V7 en 1979); les versions antérieures desh
(qui faisaient appel/etc/glob
à des caractères génériques sans guillemets d'où vient le nom du glob ) se comportaient commecsh
ouzsh -o cshnullglob
, c'est-à-dire/etc/glob
annuleraient la commande si aucun des globs n'avait de correspondance (et supprimeraient les globs non correspondants si au moins l'un d'eux avait un match). Le comportement a été rompu par l'obus Bourne.la source
rm
et non du shell. Quelque chose comme "rm: ne peut pas supprimer" * ": aucun fichier ou répertoire".emulate sh -c 'rm -- *'
pour obtenir le comportement (buggy IMO) du shell Bourne.rm
erreurs. C'est quelque chose que vous feriez dans d'autres shells pour supprimer l'erreur lorsqu'il n'y a pas de fichier correspondant et qui provoque également la suppression des erreurs rm authentiques. Ma réponse souligne cela et, espérons-le, montre comment le comportement zsh est préférable.