De ce programul unix mv nu are nevoie de opțiunea -R (recursiv) pentru directoare, dar cp are nevoie de ea? (Unix, Director, Redenumiți, Cp)

wobmene a intrebat.

Întotdeauna mă încurc când trebuie să folosesc cp sau mv: „am nevoie de -R atunci când lucrez cu dir?” În GNU coreutils cp are nevoie de -R și mv nu are nevoie.

Pur și simplu nu găsesc niciun motiv pentru care cp are nevoie de -R opțiunea de copiere a directoarelor și mv nu are nevoie. Cred că cping dirs fără -R (dar care se comportă recursiv ca și cum ar exista -R și ca mv face) nu ar cauza nicio problemă, cu excepția ruperii obiceiurilor cuiva de a utiliza instrumentul.

Cunoașteți vreo explicație? Poate că a avut un motiv cu mult timp în urmă?


Întrebare suplimentară: de ce dezvoltatorii coreutils nu fac cp să copieze în mod recursiv în mod implicit?

3 răspunsuri
derobert

Un director este (din punct de vedere conceptual) un „fișier” special care conține o listă de nume și numerele de inode la care indică aceste nume. Unele dintre nume pot fi subdirectoare. Există o intrare specială .. care indică directorul părinte.

Așadar, este clar că schimbarea numelui unui fișier este ușoară: trebuie doar să schimbați numele în intrarea din director, nimic altceva. Acest lucru este valabil indiferent dacă fișierul este de fapt un fișier sau este un „fișier” utilizat pentru a stoca conținutul unui alt director. Într-adevăr, aceeași rename syscall le face pe amândouă.

Cu toate acestea, copierea este o operațiune mult mai puțin banală. Trebuie să accesați ar putea copia doar directorul „file”, dar atunci ați avea două directoare în care fișierele sunt identice (ar fi hardlink-uri). Dacă ați avea un sistem care să permită hardlink-uri la directoare, acestea ar fi la, dar cum nici un sistem modern nu permite acest lucru, cel puțin pentru cei care nu sunt rădăcini, trebuie să faceți această copiere pentru fiecare subdirectorat. De fapt, puteți cere cp acest comportament cu cp -lR: -l for hard link, -R pentru această recursivitate.

Dar probabil că nu vă doriți să lăsați totul legat. În schimb, doriți cp să copiați fiecare fișier. Aceasta este o operațiune destul de costisitoare: fiecare fișier trebuie să fie citit în memorie și scris înapoi pe disc într-o a doua locație. De fapt, este nevoie de mai multe apeluri de sistem, pentru a deschide, citi, scrie și închide fișierele, iar acest lucru trebuie repetat pentru fiecare fișier.

Sistemele de fișiere tradiționale funcționează în acest fel și pe disc. Nu există nicio modalitate de a copia o mulțime de fișiere, în afară de a trece prin fiecare fișier în parte și de a-l copia, iar acestea sunt tipurile de sisteme de fișiere care erau utilizate atunci când au fost concepute utilitățile de bază ale liniei de comandă.

Comentarii

  • este mvde la un sistem de fișiere la altul este același lucru cu „doar schimbați numele din intrarea în director”? –  > Por wobmene.
  • Nu, trecerea de la un sistem de fișiere la altul este același lucru cu o copie + ștergere (într-adevăr, sistemul de fișiere rename syscall va eșua pentru cross-filesystem). Nu sunt sigur dacă, din punct de vedere istoric, mv chiar a acceptat mișcările cross-fs. –  > Por derobert.
  • Pot să vă spun, din experiență directă, nu din speculații, că clasicul mv nu a sprijinit mișcările între dispozitive. Acesta obișnuia să încerce doar o rename() și imprima un mesaj de eroare dacă nu reușea. Încă îmi amintesc sentimentul de șoc pe care l-am avut prima dată când am folosit din greșeală noua funcție. De ce durează atât de mult acest mv? Oh, face o copie recursivă pe care nu am intenționat-o! –  > Por Alan Curry.
  • @RuslanKhusnullin Opțiunile din linia de comandă pentru comenzile obișnuite sunt foarte greu de modificat, din cauza utilizării lor în scripturile shell. Este posibil ca cineva să depindă de comportamentul actual de refuz de copiere a directoarelor din cp. Lucrurile cross-fs au fost probabil judecate ca fiind mai puțin susceptibile de a provoca întreruperi, deși, după cum puteți vedea, tot l-a surprins pe Alan. –  > Por derobert.
  • @derobert, nu a fost așa (cross-filesystem mv a funcționat numai pentru fișiere individuale pe BSD 4.2 pe VAX). –  > Por vonbrand.
daniel kullmann

Permiteți-mi să încep prin a pune o altă întrebare:

Care este diferența dintre cp și cp -R?

Ei bine, fără -R este posibilă doar copierea fișierelor, deoarece este destul de neobișnuit ca cineva să dorească să copieze un director în mod non-recursiv: O copie non-recursivă ar avea ca rezultat un al doilea nume pentru director, care ar indica direct aceeași structură de directoare. Deoarece acest lucru este rareori ceea ce doresc oamenii, și există de fapt un program separat care face acest lucru (ln), nu este permisă copierea non-recursivă a directoarelor.

Care ar putea fi atunci diferența dintre mv și mv -R?

mv a b redenumește doar o singură intrare din director, astfel încât, dacă un director este mveste mutat, și conținutul său este mutat automat. În acest sens, mv oferă deja proprietatea recursivă, adică „redenumirea” tuturor intrărilor din directorul redenumit, de exemplu, de la a/1 la b/1. A mv care nu face acest lucru, și anume care redenumește un director a în b, , dar păstrează a/1 ca a/1, , nu este ceea ce înțeleg oamenii atunci când se referă la mutarea a ceva: când mutați un dulap, se mută și conținutul dulapului. Această altă operațiune, de mutare a unui director fără conținutul său, este de asemenea deja disponibilă, se numește mkdir.

Comentarii

  • Așa este, mă gândeam doar la cp și la mv ca operații care se numesc: „a face o copie” și „a muta”. Astfel, dacă vreau să fac o copie a unei cești de cafea, mă aștept să am o altă ceașcă de cafea cu aceeași umplutură (băutură de cafea). Problema este că instrumentele nu sunt destinate „oamenilor obișnuiți”, ci tocilarilor care sunt conștienți de structura discului și a sistemului de fișiere, nu de entități virtuale precum fișiere și directoare de fișiere. –  > Por wobmene.
  • Răspuns bine structurat și argumentat. –  > Por Spedge.
  • @RuslanKhusnullin Analogia ta cu cafeaua funcționează pentru cp și mv de asemenea – nu necesită niciun nivel de „tocilarism” pentru a o înțelege, ci doar bun simț de bază. O copie fidelă a unei cești de cafea nu este o ceașcă goală – trebuie să copiezi recursiv nu doar ceașca, ci și tot conținutul ei (cafeaua). Cu toate acestea, atunci când mutați o ceașcă de cafea, nu trebuie să mutați conținutul separat – conținutul se mișcă în mod natural odată cu recipientul. –  > Por jw013.
  • @jww013 M-ați impresionat cu „când mutați o ceașcă de cafea nu trebuie să mutați conținutul separat”, chiar are sens, vă mulțumesc. Dar este un alt nivel de abstractizare. Cred că vrei să spui „tratează un fișier ca pe un inode”, în timp ce eu mă gândesc la fișiere ca la secvențe de octeți fără meta-informații. –  > Por wobmene.
wobmene

De obicei, când sunt încurcat cu logica Unix mă uit la Plan9 pentru a vedea cum inventatorii Unix’ au implementat aceleași sarcini ani mai târziu fără să se blocheze pe compatibilitate retroactivă.

Astfel, Plan9 oferă cp și mv instrumente pentru a opera doar cu fișiere.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

Pentru copierea unui dir există dircp care este într-adevăr @{cd fromdir && tar c .} | @{cd todir && tar xT} (sintaxa rc shell)

Pentru mutarea unui dir cred că există doar dircp d1 d2 && rm -r d1

Cred că această decizie de a limita cp și mv doar pentru operațiile cu fișiere (nu cu directoare) aduce mai multă claritate în ceea ce privește operațiile pe disc și utilizarea tar pentru copierea arborilor de fișiere este foarte confortabilă pentru înțelegere și scripting.