Y a-t-il des inconvénients à définir «noclobber»?

20

Étant donné que zshpeut assommer tous les fichiers avec la commande:

>*

Je pense que définir l'option noclobberserait une bonne idée.

Je peux toujours utiliser >| filesi je veux utiliser le comportement de clobber par défaut dans bash et zsh. (zsh autorise également la syntaxe alternative >!file).

Je suppose que ce noclobbern'est pas réglé par défaut à cause de la compatibilité POSIX, mais juste pour être sûr:

Y a-t-il des inconvénients à la configuration noclobber?

Est-il possible de définir noclobberuniquement pour le shell interactif?

Tom Hale
la source
3
Je suis surpris que zsh ne prévienne pas au moins à ce sujet, étant donné qu'il avertit de quelque chose comme rm *...
ilkkachu

Réponses:

24

La raison noclobbern'est pas définie par défaut est la tradition. En ce qui concerne la conception de l'interface utilisateur, c'est une bonne idée de faire de "créer ce nouveau fichier" l'action facile et de mettre un obstacle supplémentaire l'action la plus dangereuse "soit créer un nouveau fichier ou écraser un fichier existant". C'est donc noclobberune bonne idée ( >pour créer un nouveau fichier, >|pour écraser potentiellement un fichier existant) et ce serait probablement la valeur par défaut si le shell avait été conçu quelques décennies plus tard.

Je recommande fortement d'utiliser ce qui suit dans votre fichier de démarrage du shell interactif ( .bashrcou .zshrc):

set -o noclobber
alias cp='cp -i'
alias mv='mv -i'

Dans chaque cas (redirection, copie, déplacement), l'objectif est d'ajouter un obstacle supplémentaire lorsque l'opération peut avoir pour effet secondaire d'effacer certaines données existantes, même si l'effacement des données existantes n'est pas l'objectif principal de l'opération. Je ne mets pas rm -idans cette liste car l'effacement des données est l'objectif principal de rm.

Notez cela noclobberet ce -isont des filets de sécurité . S'ils se déclenchent, vous avez fait quelque chose de mal . Ne les utilisez donc pas comme excuse pour ne pas vérifier ce que vous écrasez! Le fait est que vous devriez avoir vérifié que le fichier de sortie n'existe pas. Si on vous dit file exists: fooou overwrite 'foo'?, cela signifie que vous avez fait une erreur et que vous devriez vous sentir mal et être plus prudent. En particulier, ne prenez pas l'habitude de dire ysi vous êtes invité à écraser (sans doute, les alias devraient l'être alias cp='yes n | cp -i' mv='yes n | mv -i', mais en appuyant sur Ctrl+, Cla sortie est meilleure): si vous vouliez écraser, annuler la commande, déplacer ou supprimer la sortie fichier et réexécutez la commande.

Il est également important de ne pas prendre l'habitude de déclencher ces sécurités car si vous le faites, vous serez un jour sur une machine qui n'a pas votre configuration, et vous perdrez des données car les protections sur lesquelles vous comptiez ne sont pas '' t là.

noclobberne sera défini que pour les shells interactifs, car .bashrcou .zshrcn'est lu que par les shells interactifs. Bien sûr, vous ne devez pas modifier les options du shell d'une manière qui affecterait les scripts, car cela pourrait casser ces scripts.

Gilles 'SO- arrête d'être méchant'
la source
6
rma une option -Ique j'utilise et recommande: "invite une fois avant de supprimer plus de trois fichiers, ou lors de la suppression récursive; moins intrusif que -i, tout en offrant une protection contre la plupart des erreurs"
Reid
9
Je recommande fortement de ne pas reclasser le cp et le mv de cette façon. Cependant, leur utilisation -icomme argument par défaut est une excellente idée, mais elle devrait être appliquée à différents noms d'alias , pas aux originaux (par exemple, je mets toujours alias copy="cp -i"et alias move="mv -i"dans mon .bashrc). Pourquoi? En raison du mode de défaillance. Que se passe-t-il lorsque vous utilisez une machine ou un utilisateur différent qui ne possède pas les alias cp / mv? Fichiers potentiellement écrasés involontairement (éventuellement non détectés!). Mode d'échec correspondant avec alias copier / déplacer: le shell se plaint de ne pas reconnaître la commande.
hlovdal
1
Il existe également un mode d'échec supplémentaire pour l'alias cp / mv: lors de l'écriture d'un script shell, quelqu'un qui est habitué à l'alias cp = "cp -i" peut écrire une commande cp en s'attendant à tort à se comporter comme dans un mode interactif car il n'y a pas différence de nom. En revanche, chaque fois que j'écris "copier un fichier / un / où", je sais que j'utilise un alias et non la commande cp directement. Et même si je mettais une copie dans un fichier shell, cela échouerait de la même manière que pour un shell avec un alias manquant.
hlovdal
1
Donc TL; DR, le conseil par défaut d'utiliser l' -iargument pour cp et mv est excellent, mais le conseil de réutiliser les noms cp et mv est horriblement mauvais. C'est tellement mauvais que je dois donner à la réponse un vote négatif. Veuillez changer pour utiliser différents noms d'alias et je lui donnerai un vote positif.
hlovdal
1
@TomHale Vous pourriez utiliser alias RM='command rm', ce qui indiquerait à zsh d'utiliser la commande externe rmau lieu de l'alias. De cette façon, vous n'avez pas besoin de --interactive=neverremplacer un précédent -i.
Adaephon
6

La définition de l' noclobberoption shell dans ~/.bashrc(pour bash) ou ~/.zshrc(ou plus précisément $ZDOTDIR/.zshrcpour zsh) la rendra active dans les sessions shell interactives.

Les shells (scripts) non interactifs ne lisent pas ces fichiers.

Les options de shell ne sont généralement pas héritées des shells parents.

Cela signifie que vous devriez pouvoir définir l'option dans ces fichiers sans modifier le comportement des scripts existants, à moins que les scripts ne sources explicitement ces fichiers.

Le seul inconvénient de cela, c'est que vous oublierez à plusieurs reprises que vous avez défini l'option, au moins au début. Plus tard, comme avec tout ce genre de choses, vous commencerez à utiliser habituellement >|, même dans les cas où vous ne voudrez pas réellement encombrer le fichier (tout comme les personnes avec des alias pour rm, cpet mvavec l' -ioption toujours définie, finissent par commencer à toujours utiliser -fsur la ligne de commande).

Kusalananda
la source
2
Avec bash, les options sont héritées si $SHELLOPTS( $BASHOPTSpour shoptcelles-ci) se trouve dans l'environnement (ce n'est pas quelque chose que vous voudriez généralement faire pour ce genre de raison).
Stéphane Chazelas
3

L'inconvénient est que, si vous vous habituez à être noclobberactif, vous utiliserez un jour un système où il ne sera pas actif et vous exécuterez allègrement une commande potentiellement dangereuse, en espérant que cela noclobbervous sauvera ... et ce ne sera pas le cas. Et puis vous devrez espérer qu'il existe une sauvegarde assez récente pour récupérer les données que vous avez détruites car vous supposiez que l'on vous demanderait d'abord une confirmation.

Dave Sherohman
la source
Bien sûr, un jour, vous utiliserez un système où il n'est pas actif. Lorsque vous utilisez un système que vous ne connaissez pas, vous devez être particulièrement prudent et vous assurer que les sauvegardes sont à jour avant de faire quoi que ce soit potentiellement destructeur comme rediriger la sortie vers un fichier.
Gilles 'SO- arrête d'être méchant'