Perché `cp` e` rm` trattano le directory separatamente?


10

Perché agli strumenti piacciono cpe rmtrattano le directory separatamente dai normali file? Entrambi richiedono all'utente di specificare esplicitamente che desidera un comportamento ricorsivo, altrimenti non si occuperanno affatto delle directory.

La mia prima interazione (qualche tempo fa) con i computer era su un ambiente Windows / GUI / point-and-click / drag-and-drop, sembrava sempre naturale che queste operazioni si comportassero allo stesso modo, indipendentemente dalla destinazione.

Questo comportamento mi frustra particolarmente quando do comandi con caratteri jolly. Cosa succede se desidero rimuovere tutto in una directory ( *) tranne i sottodir non vuoti ?

Posso solo immaginare che questa sia una sorta di funzione di sicurezza per impedire all'utente di spararsi ai piedi, ma questo contraddice la mia comprensione di alcuni principi Unix:

  • Unix di solito non protegge l'utente da se stessa. Si è sempre presupposto che l'utente sappia cosa sta facendo.
  • Per Unix tutto è un file. Una directory non è solo un altro file? Perché sono trattati in modo diverso?

Le mie domande:

  • Questo comportamento deriva da una limitazione tecnica o è una scelta deliberata?

E nel caso di quest'ultimo,

  • ci sono resoconti storici delle ragioni che hanno motivato questa scelta?

Per rmlo meno, se si vuole ignorare la differenza tra file e directory, si può mettere nel vostro ~/.bashrcfile di: alias rm='rm -r'.
BenjiWiebe,

1
Vedi anche la diversa ma correlata domanda unix.stackexchange.com/questions/46066/…
derobert

1
Non è possibile confrontare cp e rm con il file manager di Windows. Avviare cmd.exe e provare a copiare, eliminare e confrontare il comportamento.
ott--

Risposte:


11

Di Derobert programma Perché unix mv non ha bisogno -R (ricorsiva) l'opzione per le directory, ma cp ha bisogno di esso? fondamentalmente risponde alla tua domanda: copiare o rimuovere un file normale è diverso dal fare la stessa operazione con una directory, perché per una directory devi elaborare tutti i file in essa contenuti. Quindi l'operazione è sostanzialmente diversa.

Vale anche la pena notare che esiste un'utilità speciale rmdirche può agire solo su directory vuote. Senza controllare i fatti, ciò porta a concludere che forse in origine rmera solo possibile rimuovere le non-directory e la rimozione profonda doveva essere ottenuta usando ricorsivamente rmle directory vuote e quindi rmdirrimuoverle.


rmdirè anche il nome della chiamata di sistema utilizzata per eliminare una directory. La directory deve essere vuota per la chiamata di sistema e l'utilità con lo stesso nome è solo "front-end", simile al unlinkcomando e all'utilità.
Giordania

Esatto - questo è ciò che mi porta a credere che in origine rmnon sarebbe stato in grado di rimuovere affatto le directory (perché le utility da riga di comando sono spesso dei wrapper relativamente semplici attorno a syscalls).
peterph

Il titolo della mia domanda potrebbe indurre in errore a pensare che sto chiedendo dei dettagli tecnici. Stavo chiedendo se è una scelta deliberata. Mi chiedo se sono l'unico a pensare che dal punto di vista dell'utente finale questo comportamento sia incoerente. Sto accettando la tua risposta perché indirettamente risponde alla mia domanda: i limiti tecnici negli interni di Unix (a livello di scala di grigi) sembrano essere l'origine di questo comportamento e l'eredità probabilmente ci impedisce di farlo diversamente oggi. I "semplici involucri attorno ai syscalls" non dovrebbero darci comportamenti più intelligenti?
Rahmu,

2
Dal POV dell'utente finale, sembra davvero strano, ma in realtà ti stavi chiedendo delle ragioni. :) Per quanto riguarda gli involucri, tutto dipende da quanto sono "semplici" (e da ciò che vuoi ancora definire "semplici"). Modern rmsicuramente non è solo un semplice wrapper (è in grado di rimuovere contemporaneamente i file mroe e anche le directory). Se non ti piace dargli l' -ropzione, usa la funzionalità di aliasing della tua shell o crea il tuo wrapper che lo metterà in atto (che sarebbe più lento, ma indipendente dalla shell che stai usando).
peterph

2

In alcune versioni UNIX, la pagina man di rm la specifica come comando per scollegare un file.
In UNIX, i file sono oggetti nel filesystem chiamato Inodes, senza nomi o posizione a parte un ID nel filesystem. I loro nomi sono riferimenti a loro in varie directory, che sono un tipo di file che sta indicizzando i file (o directory, poiché sono file) che sono elencati in esso.
Quando si annulla il collegamento di un file, il conteggio dei riferimenti del file diminuisce e quando raggiunge 0, viene infatti eliminato, poiché è contrassegnato come libero dal file system e anche i suoi blocchi / estensioni sono contrassegnati come liberi.

Se hai avuto la possibilità di rm una directory senza prima scollegare i file al suo interno, raggiungerai un punto in cui hai degli inode referenziati nel tuo filesystem ma non puoi accedervi in ​​alcun modo normale.
Poiché esiste un riferimento in base al conteggio dei riferimenti, non vengono contrassegnati come eliminati e diventano file persi.
Ciò diventa ancora più complesso quando i "file" persi sono directory e, come tale, aumenta la quantità potenziale di memoria persa nel filesystem.

Quindi è stato aggiunto rm -r, come funzionalità per facilitare la vita degli utenti UNIX, a scapito dello "spirito UNIX" standard, in quanto è più complesso delle classiche utility UNIX in quanto scende nelle directory e rimuove i file all'interno,

Inoltre, nei primi tempi di UNIX, i sistemi non avevano molta memoria e la mappatura della struttura ricorsiva di una directory comportava una penalità prestazionale, e talvolta era impossibile fare a meno di suddividere il lavoro.

cp, legge un file e lo copia, blocco per blocco. Se dovesse copiare una directory allo stesso modo di un file, aggiungerebbe riferimenti ai file all'interno senza aumentare il loro conteggio dei riferimenti, il che potrebbe portare a dati incoerenti (se la lettura / scrittura su un inode che è contrassegnato come libero dal loro blocco l'inode originale è stato eliminato), i dati persi - poiché l'eliminazione dell'ultimo riferimento (noto) a un file potrebbe causare il riciclo del suo numero di inode.

Per la folla tl; dr: le
directory in UNIX sono un tipo di file, questo è vero, ma poiché le informazioni al loro interno sono trattate in modo diverso dal sistema, poiché sono metadati del filesystem, i comandi che manipolano i file non possono funzionare su directory senza un cambiamento nel loro comportamento per manipolare anche i metadati dipendenti.

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.