L'espressione .*
viene ampliato da bash per includere le directory corrente e padre:
$ 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 eseguo rm -rf .*
sulla mia Debian usando GNU bash, version 4.2.36(1)-release
e rm
da rm (GNU coreutils) 8.13
, ricevo questo messaggio:
$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'
È una cosa GNU o è POSIX? Ci sono sistemi *nix in cui il comando sopra eliminerà silenziosamente .
e ..
?
Inoltre, è una caratteristica di sicurezza della shell o di rm
comando stesso?
Risposta accettata:
L'ultima versione (a partire dal 2017) delle specifiche POSIX per rm
l'utilità è qui (e quella precedente lì) e vieta la cancellazione di .
e ..
.
Se uno dei file punto o punto-punto è specificato come parte del nome di base di un operando (ovvero, il componente del percorso finale) o se un operando si risolve nella directory principale, rm scriverà un messaggio diagnostico di errore standard e non farà nulla di più con tali operandi.
Come notato da @jlliagre, la parte su /
è un'aggiunta in SUSv4.
La più vecchia specifica Unix disponibile pubblicamente che sono riuscito a trovare (XPF4 CAE rev2 (1994)), ha già specificato che .
e ..
non può essere rimosso, anche se i commenti nel log delle modifiche di GNU fileutils suggeriscono che era già il caso delle specifiche POSIX precedenti.
Nota che si applica a dir/..
e ../
anche, ma alcune implementazioni (incluse quelle certificate UNIX come Solaris 11 e macOS) non garantiscono ancora rm -rf ../
o rm -rf .*/
).
storia
Le prime unice
Il -r
opzione per rm
è stato aggiunto in Unix V3 (1973) anche se eliminava solo il contenuto delle directory, dovresti comunque usare rmdir
per rimuovere le directory.
Ciò è cambiato in Unix V7 (1979, la versione che ha introdotto anche la shell Bourne e da cui deriva la maggior parte degli Unice). rm -r
ora rimuoveva anche le directory e non cancellerebbe il ..
albero di directory. La pagina man afferma:
È vietato rimuovere il file ..
semplicemente per evitare le conseguenze antisociali di fare inavvertitamente qualcosa come rm -r .*
.
(sebbene si possa obiettare che rm -r .*
è ancora antisociale poiché elimina tutto perché .
è incluso).
Ha comunque accettato di rimuovere .
anche se non scollegherebbe il .
o ..
inserimenti. Quindi, rm -r .
era un modo efficace per svuotare la directory corrente.
Nota anche che la protezione era solo per un letterale ..
argomento, non per dir/..
o ./..
. Quindi, rm -rf ./.*
rimuoverebbe comunque tutto nella directory principale in modo ricorsivo.
È interessante vedere che questo era già un modo per aggirare il bug/funzionamento errato per cui i glob potevano includere .
e ..
nella loro espansione. Questo è 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 POSIX sh
lingua che richiede l'espansione di .*
per includere .
e ..
se vengono restituiti da readdir()
(bash
risolve il problema in parte solo con shopt -s dotglob
dove glob (tranne .xxx
quelli) non includono .
o ..
e con ksh
, puoi risolverlo facendo FIGNORE='@(.|..)'
).
Quando vieta esattamente .
inoltre è stato aggiunto che non è sempre chiaro e varia con ogni Unix. Alcuni risultati di seguito.
BSD
Il divieto di .
è stato aggiunto tra 2.9BSD (1983) e 2.10BSD (1987) e tra 4.2BSD (1983) e 4.3BSD (1986) (vedi questa modifica con timestamp 1985 in unix-history-repo).
$ 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/..
, vedi questa modifica nel 1988 (BSD 4.3 Net/1).
Ad oggi, il rm
di FreeBSD (e derivati come macOS) svuota ancora la directory corrente o genitore su rm -rf ./
o rm -rf ../
benchè (importa per rm -rf .*/
).
Sistema V
Non ho molte informazioni in quanto né il codice sorgente né il file binario sono pubblicamente disponibili per i derivati AT&T Unix dopo la V7. Nel suo manuale online, HPUX (basato su System III) menziona ancora che proibisce solo ..
mentre effettivamente proibisce entrambi, il che indica che probabilmente almeno SysIII non ha proibito la cancellazione di .
(modifica :Ora guardando il SysIII rm
codice sorgente, è praticamente invariato rispetto a Unix V7).
Tutti gli altri manuali online che ho controllato menzionano l'eliminazione di .
o ..
è vietato che dovrebbe essere conforme a POSIX.
Solaris rm
svuota ancora la directory corrente o principale su rm -rf ./
o rm -rf ../
.
GNU
Il registro delle modifiche iniziale per le utility file GNU contiene tutte le informazioni storiche.
Mentre originariamente non si eliminava .
o ..
erano vietati, ..
è stato vietato prima e poi entrambi (incluso dir/.
), tutti tra il 1990 e il 1991.
altro
Come abbiamo visto, in zsh
, l'espansione di .*
(o qualsiasi globo) non include mai .
o ..
(anche in sh
modalità di emulazione). Il rm
builtin (che ottieni se zmodload zsh/files
) pertanto non tratta .
o ..
appositamente. Quindi, con quel zsh
integrato, puoi rm -rf .
o rm -rf ..
per svuotare .
o ..
, ma rm -rf .*
non rimuoverà .
o ..
.
Nella casella occupata rm
, il divieto di cancellazione di .
e ..
è stato aggiunto in 0,52 (2001)