J'ai testé cp
avec les commandes suivantes:
$ ls
first.html second.html third.html
$ cat first.html
first
$ cat second.html
second
$ cat third.html
third
Ensuite, je copie first.html
à second.html
:
$ cp first.html second.html
$ cat second.html
first
Le fichier second.html
est écrasé en silence sans aucune erreur. Cependant, si je le fais dans une interface graphique de bureau en faisant glisser et en déposant un fichier avec le même nom, il sera suffixé comme first1.html
automatiquement. Cela évite d'écraser accidentellement un fichier existant.
Pourquoi ne cp
suit-il pas ce modèle au lieu d'écraser les fichiers en silence?
cp
pascp -i
ou similaire parce que vous vous habituerez à avoir un filet de sécurité, rendant les systèmes là où ils ne sont pas disponibles (la plupart d'entre eux) beaucoup plus risqués. Mieux vaut vous apprendre régulièrement,cp -i
etc. si c'est ce que vous préférez.Réponses:
Le comportement d'écrasement par défaut de
cp
est spécifié dans POSIX.Lorsque la spécification POSIX a été écrite, il existait déjà un grand nombre de scripts, avec une hypothèse intégrée pour le comportement d'écrasement par défaut. Beaucoup de ces scripts ont été conçus pour s'exécuter sans présence directe de l'utilisateur, par exemple en tant que tâches cron ou autres tâches d'arrière-plan. Changer le comportement les aurait brisés. Les examiner et les modifier tous pour ajouter une option pour forcer l'écrasement partout où cela était nécessaire était probablement considéré comme une tâche énorme avec des avantages minimes.
De plus, la ligne de commande Unix a toujours été conçue pour permettre à un utilisateur expérimenté de travailler efficacement, même au détriment d'une courbe d'apprentissage difficile pour un débutant. Lorsque l'utilisateur entre une commande, l'ordinateur doit s'attendre à ce que l'utilisateur le veuille vraiment, sans aucune hésitation; il est de la responsabilité de l'utilisateur de faire attention aux commandes potentiellement destructrices.
Lorsque l'Unix d'origine a été développé, les systèmes avaient alors si peu de mémoire et de stockage de masse par rapport aux ordinateurs modernes que l'écrasement des avertissements et des invites était probablement considéré comme un luxe inutile et inutile.
Lorsque la norme POSIX a été rédigée, le précédent était fermement établi et les rédacteurs de la norme étaient bien conscients des vertus de ne pas rompre la rétrocompatibilité .
En outre, comme d'autres l'ont décrit, tout utilisateur peut ajouter / activer ces fonctionnalités pour lui-même, en utilisant des alias de shell ou même en créant une
cp
commande de remplacement et en les modifiant$PATH
pour trouver le remplacement avant la commande système standard, et obtenir le filet de sécurité de cette façon si voulu.Mais si vous le faites, vous constaterez que vous créez un danger pour vous-même. Si la
cp
commande se comporte d'une manière lorsqu'elle est utilisée de manière interactive et d'une autre façon lorsqu'elle est appelée à partir d'un script, vous ne vous souvenez peut-être pas que la différence existe. Sur un autre système, vous pourriez finir par être négligent parce que vous êtes habitué aux avertissements et aux invites de votre propre système.Si le comportement des scripts correspond toujours à la norme POSIX, vous vous habituerez probablement aux invites en utilisation interactive, puis écrivez un script qui effectue une copie de masse - et constatez ensuite que vous avez écrasé quelque chose par inadvertance.
Si vous appliquez également l'invite dans les scripts, que fera la commande lorsqu'elle sera exécutée dans un contexte sans utilisateur, par exemple des processus d'arrière-plan ou des tâches cron? Le script sera-t-il bloqué, abandonné ou écrasé?
Suspendre ou abandonner signifie qu'une tâche qui était censée être effectuée automatiquement ne sera pas effectuée. Le non-écrasement peut parfois également causer un problème en lui-même: par exemple, il peut entraîner le traitement deux fois des anciennes données par un autre système au lieu d'être remplacées par des données à jour.
Une grande partie de la puissance de la ligne de commande vient du fait qu'une fois que vous savez comment faire quelque chose sur la ligne de commande, vous saurez également implicitement comment le faire automatiquement par script . Mais cela n'est vrai que si les commandes que vous utilisez de manière interactive fonctionnent exactement de la même manière lorsqu'elles sont appelées dans un contexte de script. Toute différence significative de comportement entre une utilisation interactive et une utilisation scriptée créera une sorte de dissonance cognitive qui dérange un utilisateur expérimenté.
la source
rm -rf
est-il si efficace, même si vous ne vouliez pas l'exécuter dans votre répertoire personnel ...cp
vient du début d'Unix. Il était là bien avant que la norme Posix ne soit écrite. En effet: Posix vient d'officialiser le comportement existant decp
à cet égard.On parle d'Epoch (01/01/1970), quand les hommes étaient de vrais hommes, les femmes étaient de vraies femmes et de petites créatures à fourrure ... (je m'égare). À cette époque, l'ajout de code supplémentaire a agrandi le programme. C'était un problème alors, car le premier ordinateur qui exécutait Unix était un PDP-7 (extensible à 144 Ko de RAM!). Les choses étaient donc petites, efficaces, sans dispositifs de sécurité.
Donc, à cette époque, vous deviez savoir ce que vous faisiez, car l'ordinateur n'avait tout simplement pas le pouvoir de vous empêcher de faire tout ce que vous regrettiez plus tard.
(Il y a un joli dessin animé de Zevar; recherchez "zevar cerveaux assiste par ordinateur" pour retrouver l'évolution de l'ordinateur. Ou essayez http://perinet.blogspirit.com/archive/2012/02/12/zevar-et- cointe.html tant qu'il existe)
Pour ceux qui sont vraiment intéressés (j'ai vu des spéculations dans les commentaires): L'original
cp
sur le premier Unix était d'environ deux pages de code assembleur (C est venu plus tard). La partie pertinente était:(Donc, dur
sys creat
)Et, pendant que nous y sommes: la version 2 d'Unix est utilisée (code sniplet)
ce qui est également difficile
creat
sans tests ni garanties. Notez que le code C pour V2 Unixcp
est inférieur à 55 lignes!la source
cp
viennent d' éditer et de réaliser une boucle / ; Bien sûr, avec le moderne, il y a tellement de boutons qu'il doit essentiellement essayer de parvenir à destination à l'avance, et pourrait facilement vérifier l'existence en premier (et le fait avec / ), mais si les attentes ont été établies à partir d' outils originaux et dépouillés , changer ce comportement briserait inutilement les scripts existants. Ce n'est pas comme des coquilles modernes avec, après tout, ne peut pas simplement faire la valeur par défaut pour une utilisation interactive.open
O_CREAT | O_TRUNC
read
write
cp
stat
cp -i
cp -n
cp
alias
cp -i
creat
se trouve être équivalent àopen
+O_CREAT | O_TRUNC
), mais le manque d'O_EXCL
expliquer pourquoi il n'aurait pas été aussi facile de gérer les fichiers existants; essayer de le faire serait intrinsèquement racé (vous devriez essentiellement vérifieropen
/stat
vérifier l'existence, puis l'utilisercreat
, mais sur les grands systèmes partagés, il est toujours possible au moment où vous y êtes arrivécreat
, quelqu'un d'autre a créé le fichier et maintenant vous avez soufflé de toute façon loin). Peut aussi bien écraser sans condition.Parce que ces commandes sont également destinées à être utilisées dans des scripts, s'exécutant éventuellement sans aucune supervision humaine, et aussi parce qu'il y a de nombreux cas où vous souhaitez en effet écraser la cible (la philosophie des shells Linux est que l'homme sait quoi elle fait)
Il y a encore quelques garanties:
cp
a un-n
|--no-clobber
optioncp
, vous vous plaindrez que le dernier n'est pas un répertoire.la source
Ce commentaire ressemble à une question sur un principe général de conception. Souvent, les questions à ce sujet sont très subjectives et nous ne sommes pas en mesure d'écrire une réponse appropriée. Soyez averti que nous pouvons fermer les questions dans ce cas.
Parfois, nous avons une explication pour le choix de conception d'origine, car les développeurs ont écrit à leur sujet. Mais je n'ai pas une si belle réponse à cette question.
Pourquoi
cp
est conçu de cette façon?Le problème est qu'Unix a plus de 40 ans.
Si vous créez un nouveau système maintenant, vous pouvez faire des choix de conception différents. Mais changer Unix briserait les scripts existants, comme mentionné dans d'autres réponses.
Pourquoi a- t-il été
cp
conçu pour remplacer silencieusement les fichiers existants?La réponse courte est "je ne sais pas" :-).
Comprenez que ce
cp
n'est qu'un problème. Je pense qu'aucun des programmes de commande d'origine protégé contre l'écrasement ou la suppression de fichiers. Le shell a un problème similaire lors de la redirection de la sortie:Cette commande écrase également silencieusement
second.html
.Je suis curieux de savoir comment tous ces programmes pourraient être repensés. Cela peut nécessiter une complexité supplémentaire.
Je pense que cela fait partie de l'explication: les premiers Unix mettaient l'accent sur les implémentations simples . Pour une explication plus détaillée de cela, voir "pire c'est mieux", lié à la fin de cette réponse.
Vous pouvez changer
> second.html
pour qu'il s'arrête avec une erreur, s'ilsecond.html
existe déjà. Cependant , comme nous l' avons mentionné, parfois l'utilisateur ne veut remplacer un fichier existant. Par exemple, elle peut créer une commande complexe, en essayant plusieurs fois jusqu'à ce qu'elle fasse ce qu'elle veut.L'utilisateur peut s'exécuter en
rm second.html
premier s'il en a besoin. Cela pourrait être un bon compromis! Il présente certains inconvénients possibles.rm
. Je voudrais donc rendre larm
sécurité aussi. Mais comment? Si nous faisonsrm
afficher chaque nom de fichier et demandons à l'utilisateur de confirmer, il doit maintenant écrire trois lignes de commandes au lieu d'une. De plus, si elle doit le faire trop souvent, elle prendra une habitude et tapera «y» pour confirmer sans réfléchir. Cela pourrait donc être très ennuyeux, et cela pourrait tout de même être dangereux.Sur un système moderne, je recommande d' installer la
trash
commande et de l'utiliser plutôtrm
que possible. L'introduction du stockage Trash était une excellente idée, par exemple pour un PC graphique à utilisateur unique .Je pense qu'il est également important de comprendre les limites du matériel Unix d'origine - RAM et espace disque limités, sortie affichée sur les imprimantes lentes ainsi que le système et le logiciel de développement.
Notez que Unix d'origine n'avait pas de tabulation , pour remplir rapidement un nom de fichier pour une
rm
commande. (De plus, le shell Bourne d'origine n'a pas d'historique de commandes, par exemple lorsque vous utilisez la touche flèche vers le hautbash
).Avec la sortie de l' imprimante, vous devez utiliser éditeur en ligne,
ed
. C'est plus difficile à apprendre qu'un éditeur de texte visuel. Vous devez imprimer certaines lignes actuelles, décider comment vous souhaitez les modifier et saisir une commande d'édition.Utiliser,
> second.html
c'est un peu comme utiliser une commande dans un éditeur de ligne. Son effet dépend de l'état actuel. (S'ilsecond.html
existe déjà, son contenu sera supprimé). Si l'utilisateur n'est pas sûr de l'état actuel, il doit s'exécuterls
ou d'ls second.html
abord."Mise en œuvre simple" comme principe de conception
Il existe une interprétation populaire de la conception Unix, qui commence:
la source
cp
un "problème"? Le faire demander interactivement la permission, ou échouer, peut être un gros problème comme ça.cat first.html second.html > first.html
cela entraînera l'first.html
écrasement du contenu desecond.html
seulement. Le contenu original est perdu pour toujours.La conception de "cp" remonte à la conception originale d'Unix. En fait, il y avait une philosophie cohérente derrière la conception Unix, qui a été légèrement moins que ce qu'on appelle à moitié en plaisantant Worse-is-Better * .
L'idée de base est que garder le code simple est en fait une considération de conception plus importante qu'avoir une interface parfaite ou "faire la bonne chose".
(c'est moi qui souligne )
En se souvenant que c'était en 1970, le cas d'utilisation de "Je veux copier ce fichier uniquement s'il n'existe pas déjà" aurait été un cas d'utilisation assez rare pour quelqu'un qui effectuait une copie. Si c'est ce que vous vouliez, vous seriez tout à fait capable de vérifier avant la copie, et cela peut même être scripté.
Quant à savoir pourquoi un OS avec cette approche de conception s'est avéré être celui qui a gagné sur tous les autres OS en cours de construction à l'époque, l'auteur de l'essai avait également une théorie pour cela.
* - ou ce que l'auteur, mais personne d'autre, n'a appelé "l'approche du New Jersey" .
la source
creat()
vsopen()
.open()
Impossible de créer un fichier si elle n'existait pas. Il ne faut 0/1/2 en lecture / écriture / les deux. Il ne prend pas encoreO_CREAT
, et il n'y en a pasO_EXCL
).La raison principale est qu'une interface graphique est par définition interactive, alors qu'un binaire
/bin/cp
est juste un programme qui peut être appelé depuis toutes sortes d'endroits, par exemple depuis votre interface graphique ;-). Je parie que même aujourd'hui, la grande majorité des appels vers/bin/cp
ne proviendront pas d'un véritable terminal avec un utilisateur tapant une commande shell, mais plutôt d'un serveur HTTP ou d'un système de messagerie ou d'un NAS. Une protection intégrée contre les erreurs des utilisateurs prend tout son sens dans un environnement interactif; moins dans un simple binaire. Par exemple, votre interface graphique appellera très probablement/bin/cp
en arrière-plan pour effectuer les opérations réelles et devra traiter les questions de sécurité sur la sortie standard même si elle vient de demander à l'utilisateur!Notez qu'il était dès le premier jour presque trivial d'écrire un wrapper sûr
/bin/cp
si vous le souhaitez. La philosophie * nix est de fournir des blocs de construction simples pour les utilisateurs: l'un d'eux en/bin/cp
est un.la source