A expressão .*
é expandida pelo bash para incluir os diretórios atual e pai:
$ 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 eu rodar rm -rf .*
no meu Debian usando o GNU bash, version 4.2.36(1)-release
e rm
de rm (GNU coreutils) 8.13
, recebo esta mensagem:
$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'
Isso é coisa do GNU ou é POSIX? Existem sistemas * nix em que o comando acima será excluído silenciosamente .
e ..
?
Além disso, esse é um recurso de segurança do shell ou do rm
próprio comando?
rm
, mas achei que valia a pena mencionar que você ainda pode ter resultados inesperados comchmod
,chown
, etc quando a correspondência.*
.Respostas:
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..
.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 contrarm -rf ../
ourm -rf .*/
).história
Unices iniciais
A
-r
opção pararm
foi adicionada no Unix V3 (1973), embora excluindo apenas o conteúdo dos diretórios, você ainda precisará usarrmdir
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:(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 paradir/..
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) efish
(2005), mas não em outros shells e, em particular, não nash
linguagem POSIX que requer a expansão de.*
incluir.
e..
se eles são retornados porreaddir()
(bash
aborda o problema parcialmente apenas comshopt -s dotglob
onde globs (exceto.xxx
os) não incluem.
ou..
, e comksh
, você pode corrigi-lo fazendo issoFIGNORE='@(.|..)'
).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 ).Para
dir/.
edir/..
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 sobrerm -rf ./
ourm -rf ../
embora (é importanterm -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 SysIIIrm
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 emrm -rf ./
ourm -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 (inclusivedir/.
), todos entre 1990 e 1991.de outros
Como vimos, em
zsh
, a expansão de.*
(ou qualquer glob) nunca inclui.
ou..
(mesmo nosh
modo de emulação). Orm
builtin (que você obtém se vocêzmodload zsh/files
), portanto, não trata.
ou..
especialmente. Portanto, com essezsh
builtin, você poderm -rf .
ourm -rf ..
esvaziar.
ou..
, masrm -rf .*
não removerá.
ou..
.No busybox
rm
, a proibição de exclusão.
e..
foi adicionada em 0,52 (2001)fonte
rm -rf . /
(observe o espaço) deve imprimir dois avisos (para.
e/
) e sair, mas parece que temos uma pergunta perguntando como se recuperar disso a cada dois meses.