A versão mais recente (a partir de 2017) da especificação POSIX para o rm
utilitário está aqui (e a anterior lá ) e proíbe a exclusão de .
e ..
.
Se um dos arquivos ponto ou ponto estiver especificado como a parte do nome de base de um operando (ou seja, o componente final do nome do caminho) ou se um operando for resolvido para o diretório raiz, a rm escreverá uma mensagem de diagnóstico para erro padrão e não fará nada mais com esses operandos.
Conforme observado por @jlliagre, a parte sobre /
é uma adição ao SUSv4.
A mais antiga especificação do Unix disponível publicamente que eu pude encontrar ( XPF4 CAE rev2 (1994)), já especificou isso .
e ..
não pode ser removida, embora comentários no changelog do arquivo GNU sugeram que esse já era o caso nas especificações POSIX mais antigas.
Note-se que ela se aplica a dir/..
e ../
bem, mas algumas implementações (incluindo aqueles UNIX certificadas como Solaris 11 e MacOS) ainda não salvaguarda contra rm -rf ../
ou rm -rf .*/
).
história
Unices iniciais
A -r
opção para rm
foi adicionada no Unix V3 (1973), embora excluindo apenas o conteúdo dos diretórios, você ainda precisará usar rmdir
para remover os diretórios.
Isso mudou no Unix V7 (1979, o lançamento que também introduziu o shell Bourne e do qual a maioria dos Unices deriva). rm -r
agora removeu os diretórios também e não excluiu a ..
árvore de diretórios. A página do manual declara:
É proibido remover o arquivo ..
apenas para evitar as conseqüências anti-sociais de se fazer algo assim inadvertidamente rm -r .*
.
(embora se possa argumentar que rm -r .*
ainda é anti - social , pois exclui tudo porque .
está incluído).
Ele ainda aceitou remover, .
mas não desvinculou as entradas .
ou ..
. Então, rm -r .
era uma maneira eficaz de esvaziar o diretório atual.
Observe também que a salvaguarda era apenas para um ..
argumento literal , não para dir/..
ou ./..
. Portanto, rm -rf ./.*
ainda removeria tudo no diretório pai recursivamente.
É interessante ver que isso já era para contornar o bug / falha de recurso pelo qual os globs poderiam incluir .
e ..
em sua expansão. Isso foi corrigido no shell Forsyth (a base do shell Minix original e do pdksh) no final dos anos 80, zsh
(1990) e fish
(2005), mas não em outros shells e, em particular, não na sh
linguagem POSIX que requer a expansão de .*
incluir .
e ..
se eles são retornados por readdir()
( bash
aborda o problema parcialmente apenas com shopt -s dotglob
onde globs (exceto .xxx
os) não incluem .
ou ..
, e com ksh
, você pode corrigi-lo fazendo isso FIGNORE='@(.|..)'
).
Quando exatamente proibir .
também foi adicionado nem sempre é claro e varia de acordo com cada Unix. Algumas descobertas abaixo.
BSDs
A proibição de .
foi adicionada em algum momento entre 2.9BSD (1983) e 2.10BSD (1987) e entre 4.2BSD (1983) e 4.3BSD (1986) (veja essa alteração com timestamp 1985 em 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");
Para dir/.
e dir/..
veja esta alteração em 1988 (BSD 4.3 Net / 1).
Até essa data, o rm
FreeBSD (e derivados como o macOS) ainda esvazia o diretório atual ou pai sobre rm -rf ./
ou rm -rf ../
embora (é importante rm -rf .*/
).
Sistema V
Não tenho muita informação, pois nem a fonte nem o binário estão disponíveis publicamente para os derivados da AT&T Unix após a V7. Em seu manual online, HPUX (com base no Sistema III) ainda menciona que apenas proíbe ..
enquanto efetivamente proíbe tanto que é uma indicação de que, provavelmente, pelo menos SysIII não proibiu a exclusão de .
( edição : Agora, olhando para o SysIII rm
código-fonte , é praticamente inalterado desde o Unix V7).
Todos os outros manuais on-line que verifiquei mencionam a exclusão .
ou ..
são proibidos, o que é esperado que seja compatível com POSIX.
O Solaris rm
ainda esvazia o diretório atual ou pai em rm -rf ./
ou rm -rf ../
.
GNU
O registro de alterações antecipado dos arquivos do GNU possui todas as informações históricas.
Embora originalmente não excluísse .
ou ..
fosse proibido, ..
era proibido primeiro e depois ambos (inclusive dir/.
), todos entre 1990 e 1991.
de outros
Como vimos, em zsh
, a expansão de .*
(ou qualquer glob) nunca inclui .
ou ..
(mesmo no sh
modo de emulação). O rm
builtin (que você obtém se você zmodload zsh/files
), portanto, não trata .
ou ..
especialmente. Portanto, com esse zsh
builtin, você pode rm -rf .
ou rm -rf ..
esvaziar .
ou ..
, mas rm -rf .*
não removerá .
ou ..
.
No busybox rm
, a proibição de exclusão .
e ..
foi adicionada em 0,52 (2001)
rm
, mas achei que valia a pena mencionar que você ainda pode ter resultados inesperados comchmod
,chown
, etc quando a correspondência.*
.