Por que rm * (1) * remove todos os arquivos em um diretório?

47

Eu esperei isso:

$ rm *(1)*

removeria todos os arquivos que contêm (1)o nome. Eu estava errado. Ele removeu todos os arquivos no diretório.

Por quê?

Eric Wilson
fonte
5
Sempre que uso rmcom um padrão, sempre o antecedo echoantes de emitir o comando real. O hábito me salvou mais de uma vez (desde então, aos 6 anos de idade, confundindo a diferença entre DEL A: *.*e DEL *.* A:).
gerrit

Respostas:

51

De man bash:

*(pattern-list)
                 Matches zero or more occurrences of the given patterns

Você tem uma expressão glob que corresponde aos arquivos que começam com zero ou mais 1s - que são todos os arquivos.

Uma maneira simples de desativar esse comportamento globbing é \escapar dos parênteses:

rm *\(1\)*

Caso contrário, você pode usar shopt -u extglobpara desativar o comportamento e shopt -s extglobreativá-lo:

shopt -u extglob
rm *(1)*
shopt -s extglob

Observe que, como diz Stephane , extglobé habilitado bash-completiondesabilitando-o, podendo fazer com que as funções de conclusão não funcionem corretamente.

Graeme
fonte
7
Observe que extglobnão está ativado por padrão, mas está ativado por bash_completion se você tiver o instalado e ativado. bashnão tem escopo local para opções como o zshfaz.
Stéphane Chazelas
11
Observe também que bash-4.3há uma regressão que *(1)*também expande arquivos ocultos.
Stéphane Chazelas
@StephaneChazelas Você tem um link para o bug relacionado a essa regressão? Obrigado
Básico
2
@ Básico, aqui vai você . Chet ainda não respondeu.
Stéphane Chazelas
9

Isso provavelmente está relacionado à extglobopção de shell. Se eu desligá-lo, o padrão produz uma mensagem de erro:

martin@dogmeat:~$ shopt -u extglob
martin@dogmeat:~$ shopt extglob
extglob         off
martin@dogmeat:~$ echo *(1)*
bash: syntax error near unexpected token `('

Se eu ligá-lo, parece realmente combinar com tudo. A página de manual documenta esses padrões, acho que eles estão relacionados:

   If the extglob shell option is enabled using the shopt builtin, several
   extended  pattern  matching operators are recognized.  In the following
   description, a pattern-list is a list of one or more patterns separated
   by a |.  Composite patterns may be formed using one or more of the fol
   lowing sub-patterns:

          ?(pattern-list)
                 Matches zero or one occurrence of the given patterns
          *(pattern-list)
                 Matches zero or more occurrences of the given patterns
          +(pattern-list)
                 Matches one or more occurrences of the given patterns
          @(pattern-list)
                 Matches one of the given patterns
          !(pattern-list)
                 Matches anything except one of the given patterns

Não vejo nenhuma documentação que especifique o que os parênteses sem um caractere à esquerda fazem. De qualquer forma, você pode contornar o problema citando os parens:

martin@dogmeat ~ % echo *\(1\)*
A(1)b

Além disso, use echoou lspara testar seu padrão primeiro, se você não tiver certeza absoluta de que está funcionando :)

Martin von Wittich
fonte
FYI: {é uma chave, (é um parêntese (ou suporte redondo).
22614 Mikel
Ah obrigada. Eu não sou um falante nativo Inglês por isso tendem a confundi-los :)
Martin von Wittich
6
Em inglês: {= colchete, (= colchete redondo, [= colchete. Em americano: {= chave, (= paren, [= chave. Um pouco confuso. Se você precisar verificar como algo se chama, Jargon File - ASCII é bastante útil.
22614 Mikel
4
@ Mikel Obrigado, eu também verifiquei aqui , agora eu sei sobre os suportes de flores e os esquilos !
No inglês indiano, {é um suporte de flores, [é um suporte quadrado e (é um suporte redondo ou, mais comumente, apenas um suporte. :-)
ShreevatsaR