Perché il programma mv unix non ha bisogno dell'opzione -R (ricorsiva) per le directory ma cp ne ha bisogno?


58

Vengo sempre incasinato quando è necessario utilizzare cpo mv: "Ho bisogno -Rdell'opzione quando lavoro con dir?" In GNU coreutils cpha bisogno -Re mvnon lo fa.

Non riesco proprio a trovare alcun motivo per cui abbia cpbisogno -Rdell'opzione per copiare le directory e mvnon lo fa. Penso che cping dir senza -R(ma comportandosi in modo ricorsivo come c'è -Re come mv) non causerebbe problemi se non quello di rompere le abitudini di qualcuno sull'uso dello strumento.

Conosci qualche spiegazione? Potrebbe essere stato un motivo molto tempo fa?


Domanda aggiuntiva: perché gli sviluppatori coreutils non fanno cpricorsivamente le directory di copia in modo predefinito?

Risposte:


45

Una directory è (concettualmente) un "file" speciale che contiene un elenco di nomi e i numeri di inode a cui fanno riferimento questi nomi. Alcuni nomi possono essere sottodirectory. C'è una voce speciale ..che punta alla directory principale.

Quindi, è chiaro, cambiare il nome di un file è facile: basta cambiare il nome nella voce della directory, nient'altro. Indica se il file è effettivamente un file o è un "file" utilizzato per archiviare il contenuto di un'altra directory. In effetti, la stessa renamesyscall fa entrambe le cose.

Copiare, tuttavia, è un'operazione molto meno banale. Si potrebbe basta copiare il "file" directory, ma poi si sarebbe avere due directory in cui sono i file sono gli stessi (che sarebbero collegamenti fisici). Se tu avessi un sistema che consenta hardlink alle directory, lo sarebbero, ma dal momento che nessun sistema moderno lo consente, almeno al non root, devi fare quella copia per ogni sottodirectory. Puoi effettivamente chiedere cpquesto comportamento con cp -lR: -lper hard link, -Rper quella ricorsione.

Ma lasciare tutto collegato non è probabilmente quello che vuoi. Invece, vuoi cpcopiare ogni file. È un'operazione piuttosto costosa: ogni file deve essere letto in memoria e riscritto sul disco in una seconda posizione. In realtà sono necessari diversi syscall per aprire, leggere, scrivere e chiudere i file, e questo deve essere ripetuto per ogni file.

I filesystem tradizionali funzionano in questo modo anche su disco. Non c'è modo di copiare un mucchio di file, se non quello di esaminarli singolarmente e copiarli, e questi sono i tipi di filesystem che erano in uso quando sono state progettate le utility di base della riga di comando.


l' mving da un file system all'altro è lo stesso "basta cambiare il nome nella voce della directory"?
rslnx,

5
No, cross-filesystem è lo stesso di una copia + cancellazione (in effetti, il renamesyscall fallirà per cross-filesystem). Non sono sicuro che, storicamente, mvsupportassero persino le mosse cross-fs.
derobert,

9
Posso dirti, per esperienza diretta e non per speculazione, che la classica mvnon supportava le mosse tra dispositivi. Ha usato solo per provare a rename()e stampare un messaggio di errore se fallito. Ricordo ancora la sensazione scioccata della prima volta che ho usato per sbaglio la nuova funzione. Perché questa mv impiega così tanto tempo? Oh, sta facendo una copia ricorsiva che non intendevo!
Alan Curry,

5
@RuslanKhusnullin Le opzioni della riga di comando per i comandi comuni sono molto difficili da modificare, a causa del loro uso negli script di shell. Qualcuno potrebbe dipendere dall'attuale comportamento rifiuta di copiare le directory di cp. La roba cross-fs è stata probabilmente giudicata meno probabilità di causare rotture, anche se come puoi vedere, ha comunque sorpreso Alan.
derobert,

1
@derobert, non funzionava (il cross-filesystem mvfunzionava solo per singoli file su BSD 4.2 su VAX).
vonbrand,

21

Vorrei iniziare facendo un'altra domanda:

Qual è la differenza tra cpe cp -R?

Bene, senza il -Rflag, è possibile solo copiare i file, perché è piuttosto insolito che qualcuno voglia copiare una directory non ricorsiva: una copia non ricorsiva comporterebbe solo un secondo nome per la directory, che punta direttamente alla stessa directory struttura. Poiché questo è ciò che la gente desidera raramente e in realtà esiste un programma separato che fa questo ( ln), non è consentita una copia non ricorsiva di directory.

Quale potrebbe quindi essere la differenza tra mve mv -R?

mv a brinomina solo una singola voce nella directory, quindi se viene modificata una directory mv, anche i suoi contenuti vengono spostati automaticamente. In tal senso, mvfornisce già la proprietà ricorsiva, ovvero la "ridenominazione" di tutte le voci nella directory rinominata, ad es. Da a/1a b/1. Una mvche non fa quello, cioè, che rinomina una directory aper b, ma mantiene a/1come a/1, non quello che la gente capisce quando si riferiscono a muoversi qualcosa è: Quando si sposta un armadio, il contenuto della credenza vengono spostati pure. Quell'altra operazione, lo spostamento di una directory senza il suo contenuto, è già disponibile, si chiama mkdir.


2
Esatto, stavo solo pensando cpe mvcome operazioni che prendono il nome: "fai una copia" e "sposta". Quindi, se voglio fare una copia di una tazza di caffè, mi aspetto di avere un'altra tazza di caffè con lo stesso ripieno (bevanda al caffè). Il problema è che gli strumenti non sono destinati a "persone normali" ma a nerd che sono a conoscenza della struttura del disco e del file system, non di entità virtuali come i file e le directory dei file.
rslnx,

1
Risposta ben strutturata e motivata.
Spedge,

1
@RuslanKhusnullin tua analogia caffè lavora per cpe mvanche - non richiede alcun livello di "nerdness" per capire, solo di base di buon senso. Una vera copia di una tazza di caffè non è una tazza vuota: devi copiare in modo ricorsivo non solo la tazza, ma anche tutto il suo contenuto (il caffè). Tuttavia, quando sposti una tazza di caffè non devi spostare i contenuti separatamente: i contenuti si spostano naturalmente con il contenitore.
jw013,

1
@ jw013 Mi hai colpito "quando sposti una tazza di caffè non devi spostare i contenuti separatamente", ha davvero senso, grazie. Ma è un altro strato di astrazione. Penso che intendi "trattare un file come un inode" mentre penso a file come a sequenze di byte senza meta-informazioni.
rslnx,

6

Di solito quando sono incasinato con la logica Unix guardo Plan9 per vedere come gli inventori Unix hanno implementato gli stessi compiti anni dopo senza rimanere bloccati sulla retrocompatibilità.

Quindi Plan9 offre cpe mvstrumenti per operare solo con file.

`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.

Per copiare una directory c'è dircpdavvero @{cd fromdir && tar c .} | @{cd todir && tar xT}(sintassi della shell rc)

Per spostare una directory penso che ci sia solo dircp d1 d2 && rm -r d1

Penso che questa decisione di limitare cpe solo mvper le operazioni sui file (non dirs) porti più chiarezza alle operazioni del disco e l'uso tarper la copia degli alberi dei file è molto comodo per la comprensione e lo scripting.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.