Почему rm * (1) * удаляет все файлы в каталоге?

47

Я ожидал, что:

$ rm *(1)*

удалил бы все файлы, содержащиеся (1)в имени. Я ошибался. Он удалил все файлы в каталоге.

Почему?

Эрик Уилсон
источник
5
Всякий раз, когда я использую rmс шаблоном, я всегда предшествую ему echoперед выполнением фактической команды. Привычка спасала меня не раз (с тех пор, когда мне было около 6 лет, путала разницу между DEL A: *.*и DEL *.* A:).
gerrit

Ответы:

51

От man bash:

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

У вас есть выражение glob, которое соответствует файлам, начинающимся с нуля или более 1s - это все файлы.

Один простой способ отключить это глобальное поведение - \избежать скобок:

rm *\(1\)*

В противном случае вы можете использовать, shopt -u extglobчтобы отключить поведение и shopt -s extglobснова включить его:

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

Обратите внимание, что, как говорит Стефан , extglobон включен, bash-completionпоэтому его отключение может привести к неправильной работе функций завершения.

Graeme
источник
7
Обратите внимание, что extglobон не включен по умолчанию, но включен bash_completion, если он установлен и включен. bashне имеет локальной области действия для опций, как zshделает.
Стефан Шазелас
1
Также обратите внимание, что bash-4.3есть регрессия, которая *(1)*также расширяет скрытые файлы.
Стефан Шазелас
@StephaneChazelas У вас есть ссылка на ошибку, связанную с этой регрессией? Спасибо
Basic
2
@ Базовик, вот , пожалуйста . Чет еще не ответил.
Стефан Шазелас
9

Это, вероятно, связано с extglobопцией оболочки. Если я выключу его, шаблон выдаст сообщение об ошибке:

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

Если я включу его, то оно действительно будет соответствовать всему. Справочная страница документирует эти шаблоны, я думаю, что они связаны:

   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

Я не вижу никакой документации, которая бы указывала, что делают круглые скобки без ведущего символа. Во всяком случае, вы можете обойти эту проблему, цитируя скобки:

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

Кроме того, сначала используйте echoили lsдля проверки вашего шаблона, если вы не совсем уверены, что это работает :)

Мартин фон Виттих
источник
К вашему сведению: {это скобка, (это пара (или круглая скобка).
Микель
Ах, спасибо. Я не являюсь носителем английского языка, поэтому я склонен их путать :)
Мартин фон Виттих,
6
На британском языке: {= фигурная скобка, (= круглая скобка, [= квадратная скобка. На американском языке: {= скобка, (= paren, [= скобка. Немного смущает. Если вам когда-нибудь понадобится проверить, что-то называется, Jargon File - ASCII весьма полезен.
Микель
4
@Mikel Спасибо, я также проверил здесь, так что теперь я знаю о цветочных скобках и белки !
В индийском английском языке {это цветочная скобка, [квадратная скобка и (круглая скобка или чаще просто скобка. :-)
ShreevatsaR