'Rm. *' Cancella mai la directory principale?


53

L'espressione .*viene espansa da bash per includere le directory corrente e parent:

$ ls -la
total 2600
drwxrwxrwx   2 terdon terdon 2162688 Sep 10 16:22 .
drwxr-xr-x 142 terdon terdon  491520 Sep 10 15:34 ..
-rw-r--r--   1 terdon terdon       0 Sep 10 16:22 foo
$ echo .*
. ..

Se corro rm -rf .*sul mio Debian usando GNU bash version 4.2.36(1)-releasee rmda rm (GNU coreutils) 8.13, ricevo questo messaggio:

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

È una cosa GNU o è POSIX? Esistono sistemi * nix in cui il comando sopra verrà eliminato in silenzio .e ..?

Inoltre, si tratta di una caratteristica di sicurezza della shell o del rmcomando stesso?


4
So che questa domanda è nel contesto rm, ma ho pensato che fosse la pena ricordare che si può ancora avere risultati inattesi con chmod, chownecc in caso di corrispondenza .*.
Aaron Copley,

Risposte:


59

L'ultima versione (a partire dal 2017) delle specifiche POSIX per l' rmutilità è qui (e la precedente ) e proibisce la cancellazione di .e ...

Se uno dei file punto o punto-punto viene specificato come parte del nome di base di un operando (ovvero il componente nome percorso finale) o se un operando si risolve nella directory principale, rm deve scrivere un messaggio diagnostico in errore standard e non fare nulla più con tali operandi.

Come notato da @jlliagre, la parte su /è un'aggiunta in SUSv4.

Le più vecchie specifiche Unix disponibili pubblicamente che sono riuscito a trovare ( XPF4 CAE rev2 (1994)), lo hanno già specificato .e ..non possono essere rimosse, anche se i commenti nel file di logutils GNU suggeriscono che era già il caso nelle precedenti specifiche POSIX.

Si noti che si applica a dir/..e ../pure, ma alcune implementazioni (anche UNIX-certificate come Solaris 11 e MacOS) ancora non fare salvaguardia contro rm -rf ../o rm -rf .*/).

storia

Unici primi

L' -ropzione a è rmstata aggiunta in Unix V3 (1973) anche se stava solo cancellando il contenuto delle directory, dovresti comunque utilizzare rmdirper rimuovere le directory.

Ciò è cambiato in Unix V7 (1979, il rilascio che ha anche introdotto la shell Bourne e da cui deriva la maggior parte degli Unices). rm -rora rimosso anche le directory e non eliminerebbe l' ..albero delle directory. La pagina man afferma:

È vietato rimuovere il file ..semplicemente per evitare le conseguenze antisociali di fare inavvertitamente qualcosa del genere rm -r .*.

(anche se si potrebbe sostenere che rm -r .*è ancora antisociale in quanto elimina tutto perché .è incluso).

Ha comunque accettato di rimuovere .sebbene non scollegasse le voci .o ... Quindi, è rm -r .stato un modo efficace per svuotare la directory corrente.

Si noti inoltre che la salvaguardia era solo per un ..argomento letterale , non per dir/..o ./... Quindi, rm -rf ./.*rimuoverebbe tutto ricorsivamente nella directory padre.

È interessante vedere che questo era già una soluzione alternativa al bug / malfunzionamento con cui i globs potevano includere .e ..nella loro espansione. Ciò è stato risolto nella shell Forsyth (la base per la shell Minix originale e pdksh) alla fine degli anni '80, zsh(1990) e fish(2005) ma non altre shell e in particolare non il shlinguaggio POSIX che richiede l'espansione di .*includere .e ..se vengono restituiti da readdir()( bashrisolve il problema in parte solo con il punto in shopt -s dotglobcui i globs (tranne .xxxquelli) non includono .o .., e con ksh, puoi risolverlo facendo FIGNORE='@(.|..)').

Quando è .stato aggiunto esattamente anche il divieto , non è sempre chiaro e varia con ogni Unix. Alcuni risultati di seguito.

BSD

La proibizione di è .stata aggiunta qualche volta tra 2.9BSD (1983) e 2.10BSD (1987) e tra 4.2BSD (1983) e 4.3BSD (1986) (vedere questa modifica con data e ora 1985 nel repository storia unix ).

$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.9BSD/root.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `..'
$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.10bsd.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `.' or `..'
rm: cannot remove `.' or `..'\n");

Per dir/.e dir/.., vedere questa modifica nel 1988 (BSD 4.3 Net / 1).

A questa data, il rmdi FreeBSD (e derivati come MacOs) svuota ancora la directory corrente o il genitore al momento rm -rf ./o rm -rf ../se (questioni per rm -rf .*/).

Sistema V

Non ho molte informazioni in quanto né i sorgenti né i file binari sono disponibili pubblicamente per i derivati ​​Unix AT&T dopo V7. Nel suo manuale online, HPUX (basato sul Sistema III) menziona ancora che proibisce solo ..mentre in effetti proibisce entrambi, il che è un'indicazione che probabilmente almeno SysIII non ha vietato la cancellazione di .( modifica : Ora guardando il rmcodice sorgente SysIII , è praticamente invariato da Unix V7).

Tutti gli altri manuali online che ho verificato menzionano l'eliminazione .o ..è vietato che ci si aspetta che sia conforme a POSIX.

Solaris rmsvuota ancora la directory corrente o parent su rm -rf ./o rm -rf ../.

GNU

Il primo log delle modifiche per i file GNU contiene tutte le informazioni storiche.

Sebbene in origine non fossero né cancellate ...vietate, ..prima era proibito e poi entrambi (compresi dir/.), tutti tra il 1990 e il 1991.

altro

Come abbiamo visto, zshl'espansione di .*(o di qualsiasi glob) non include mai .o ..(anche in shmodalità di emulazione). Il rmbuiltin (che si ottiene se si zmodload zsh/files) quindi non tratta .o ..appositamente. Quindi, con quel zshbuilt-in, puoi rm -rf .o rm -rf ..svuotare .o .., ma rm -rf .*non rimuoverai .o ...

In busybox rm, il divieto di cancellazione di .ed è ..stato aggiunto in 0.52 (2001)


Strano, questo sembra specificare che rm -rf . /(notare lo spazio) dovrebbe stampare due avvertimenti (per .e /) ed uscire, ma sembra che ci sia una domanda che chieda come recuperarlo ogni due mesi.
Kevin,

6
@Kevin Non tutti i sistemi sono conformi a POSIX e la restrizione della directory principale è stata aggiunta esplicitamente solo nell'ultima versione POSIX.
jlliagre,

@jlliagre vedo. GNU generalmente cerca di implementare POSIX (+ estensioni, ovviamente), e immagino che vorrebbero metterlo in questo, ma se fosse abbastanza nuovo lo spiegherebbe.
Kevin,

2
@Stephane: hai ragione, ma aggiungerei ancora un grande "Sì, potrebbe succedere! Ma ..." all'inizio della tua risposta, in modo che la gente lo sappia senza dubbio su alcuni (più vecchi o semplicemente non Sistemi compatibili con POSIX, potrebbero eliminare le directory principali. Cerco di evidenziare sempre quelle possibilità (cioè, cerco di stare al sicuro, anche se a volte rende la risposta a volte più difficile da leggere / ricordare) ^^
Olivier Dulac,

1
@ MartinSchröder, Su BSD, è stato aggiunto da qualche parte tra 2.8BSD e 2.10BSD (prima che solo ".." fosse proibito come in UnixV7) e tra 3BSD e 4.3RENO. Sui sistemi SysV, è meno chiaro. Il manuale HPUX, ad esempio, afferma che proibisce solo ".." ma in effetti proibisce entrambi "." e "..", è solo il manuale che non è aggiornato.
Stéphane Chazelas,
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.