Comment se débarrasser de «Aucune correspondance trouvée» lors de l'exécution de «rm *»

22

En utilisant zsh, j'obtiens un message "Aucune correspondance trouvée" lorsque je choisis un modèle qui ne convient pas rmet 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?

user123456
la source
Essayez-vous de supprimer tout dans le répertoire actuel? Quel est le répertoire actuel?
cutrightjm
Vous pouvez utiliser setopt extended_glob(ou même simplement rm * >/dev/null 2>&1) mais vraiment vous devriez faire une solution de contournement pour ne pas avoir besoin rm *, c'est carrément dangereux
grochmal
Tu devrais vraiment couler /dev/nullplutôt dev/zero. De plus, votre redirection stderr manque un &; ça devrait l'être 2>&1.
roaima
Le message d'erreur est généré par zshpendant 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.
Adaephon

Réponses:

42

Ce comportement est contrôlé par l' nomatchoption 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écutant

setopt +o nomatch

Ensuite, 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).

Stephen Kitt
la source
4
Le comportement est également contrôlé par les options nullglobet cshnullglob. Si nullglobest 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églage cshnullgloba 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églage nullglobou cshnullglobremplacements nomatch. Vous pouvez également définir nullglobdes modèles simples en utilisant le qualificatif de glob N: rm *(N).
Adaephon
nomatchest 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 qui rmdonnera une erreur, ou pire pourrait supprimer le mauvais fichier pour un motif comme *.[ch]par exemple!
Stéphane Chazelas
9

Que voudriez-vous qu'il fasse à la place? Pas exécuté rmdu 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)?

  1. files=(*(N)); (($#files)) && rm -- $files. Ou, (rm -- *) 2> /dev/nullmais cela cacherait également de véritables erreurs rmqui seraient idiotes. Vous pouvez ignorer l' zsherreur mais restaurer stderr pour la rmcommande avec(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
  2. emulate sh -c 'rm -- *' 2> /dev/null. Ensuite, comme dans celui shqui est zshmaintenant émulé pour cette seule ligne de commande, la non-correspondance *est transmise telle quelle rmet se rmplaint car ce *fichier n'existe pas. Nous rmsupprimons le stderr de comme vous le feriez shpour supprimer ce message d'erreur, mais encore une fois, c'est idiot car cela cacherait de véritables erreurs par rmopposition à l'erreur encourue par la mauvaise conduite de shpasser un littéral *à rm. rm -f '*'ne se plaindrait pas d'un *fichier inexistant, donc vous pouvez le faireemulate sh -c 'rm -f -- *'
  3. rm -- *(N). rmse plaindrait que lorsqu'ils ne sont pas passé aucun argument, mais encore une fois, non rm -f: rm -f -- *(N).

Généralement, rm -fc'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ès rmson retour. Vous souhaitez également généralement utiliser -fdans les scripts pour éviter que l'utilisateur ne soit invité dans certaines situations.

Ici, appeler rmlorsque le glob ne correspond pas est faux. Le comportement sh1 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:

$ 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

A défaut d'une erreur est la chose la plus sensée à faire et est ce que zsh(et fish, csh, tcsh, bash -o failglobet le shell Unix d' origine) fait.

Et si vous voulez vous occuper de ce cas spécial, zshc'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 la setcommande. Donc, l'équivalent là-bas serait:

set files *
if count $files > /dev/null
  rm -f -- $files
end

Voir Pourquoi nullglob n'est-il pas par défaut pour plus de détails.


1 . À proprement parler, ce n'est que shdepuis le shell Bourne (depuis Unix V7 en 1979); les versions antérieures de sh(qui faisaient appel /etc/globà des caractères génériques sans guillemets d'où vient le nom du glob ) se comportaient comme cshou zsh -o cshnullglob, c'est-à-dire /etc/globannuleraient 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.

Stéphane Chazelas
la source
Je pense qu'il s'attend à recevoir le message d'erreur de rmet non du shell. Quelque chose comme "rm: ne peut pas supprimer" * ": aucun fichier ou répertoire".
Emmanuel
@Emmanuel, alors c'est 2: emulate sh -c 'rm -- *'pour obtenir le comportement (buggy IMO) du shell Bourne.
Stéphane Chazelas
@Stephane_Chazelas tel qu'il est écrit, 2 est la bonne réponse à une question qu'il n'a pas posée :).
Emmanuel
@Emmanuel, tous les 3 répondent à la question: comment se débarrasser de l'erreur "No match". Le code de l'OP supprime les rmerreurs. 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.
Stéphane Chazelas