¿Por qué rm * (1) * elimina todos los archivos en un directorio?

47

Yo esperaba que:

$ rm *(1)*

eliminaría todos los archivos que contengan (1)el nombre. Estaba equivocado. Eliminó todos los archivos en el directorio.

¿Por qué?

Eric Wilson
fuente
55
Siempre que lo uso rmcon un patrón, siempre lo precedo echoantes de emitir el comando real. El hábito me salvó más de una vez (desde entonces, a los 6 años, confundiendo la diferencia entre DEL A: *.*y DEL *.* A:).
gerrit

Respuestas:

51

De man bash:

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

Tiene una expresión global que coincide con los archivos que comienzan con cero o más 1s, que son todos los archivos.

Una forma simple de deshabilitar este comportamiento global es \escapar de los paréntesis:

rm *\(1\)*

De lo contrario, puede usar shopt -u extglobpara desactivar el comportamiento y shopt -s extglobvolver a habilitarlo:

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

Tenga en cuenta que, como dice Stephane , extglobse habilita al bash-completiondeshabilitarlo, lo que puede provocar que las funciones de finalización no funcionen correctamente.

Graeme
fuente
77
Tenga en cuenta que extglobno está activado de manera predeterminada, pero está activado por bash_completion si lo tiene instalado y habilitado. bashno tiene alcance local para opciones como lo zshhace.
Stéphane Chazelas
1
También tenga en cuenta que bash-4.3tiene una regresión que *(1)*también expande los archivos ocultos.
Stéphane Chazelas
@StephaneChazelas ¿Tiene un enlace para el error relacionado con esa regresión? Gracias
Básico
2
@ Básico, aquí tienes . Chet aún no ha respondido.
Stéphane Chazelas
9

Esto probablemente esté relacionado con la extglobopción de shell. Si lo apago, el patrón produce un mensaje de error:

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

Si lo enciendo, de hecho parece coincidir con todo. La página de manual documenta estos patrones, creo que están 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

No veo ninguna documentación que especifique lo que hacen los paréntesis sin un personaje principal. De todos modos, puede evitar el problema citando a los padres:

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

Además, use echoo lspara probar su patrón primero si no está absolutamente seguro de que está funcionando :)

Martin von Wittich
fuente
FYI: {es un paréntesis, (es un paréntesis (o paréntesis redondo).
Mikel
Ah gracias. No soy hablante nativo de inglés, así que tiendo a confundirlos :)
Martin von Wittich
66
En británico: {= corchete, (= corchete, [= corchete. En americano: {= paréntesis, (= paréntesis, [= paréntesis. Un poco confuso. Si alguna vez necesita verificar cómo se llama algo, Jargon File - ASCII es bastante útil.
Mikel
44
@ Mikel ¡Gracias, también lo comprobé aquí, así que ahora sé sobre los soportes de flores y los ardillas !
En inglés de la India, {es un corchete de flores, [es un corchete cuadrado y (es un corchete redondo o, más comúnmente, solo un corchete. :-)
ShreevatsaR