Dlaczego rm * (1) * usuwa wszystkie pliki z katalogu?

47

Spodziewałem się tego:

$ rm *(1)*

usunie wszystkie pliki zawarte (1)w nazwie. Myliłem się. Usunął wszystkie pliki w katalogu.

Dlaczego?

Eric Wilson
źródło
5
Ilekroć używam rmwzoru, zawsze poprzedzam go echoprzed wydaniem właściwego polecenia. Ten nawyk uratował mnie więcej niż jeden raz (od tego czasu, jako mniej więcej 6-latek, myląc różnicę między DEL A: *.*i DEL *.* A:).
gerrit

Odpowiedzi:

51

Od man bash:

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

Masz wyrażenie glob, które pasuje do plików rozpoczynających się od zera lub więcej 1s - czyli wszystkich plików.

Jednym prostym sposobem na wyłączenie tego zachowania globowania jest \uniknięcie nawiasów:

rm *\(1\)*

W przeciwnym razie możesz użyć, shopt -u extglobaby wyłączyć zachowanie i shopt -s extglobwłączyć je ponownie:

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

Zauważ, że jak mówi Stephane , extglobfunkcja ta jest włączona, bash-completiondlatego wyłączenie jej może spowodować nieprawidłowe działanie funkcji uzupełniania.

Graeme
źródło
7
Pamiętaj, że extglobnie jest domyślnie włączone, ale jest włączone przez bash_completion, jeśli masz to zainstalowane i włączone. bashnie ma lokalnego zasięgu dla opcji takich jak zsh.
Stéphane Chazelas
1
Zauważ również, że bash-4.3ma regresję, która *(1)*rozszerza również ukryte pliki.
Stéphane Chazelas
@StephaneChazelas Czy masz link do błędu związanego z tą regresją? Dzięki
Basic
2
@Basic, proszę bardzo . Chet jeszcze nie odpowiedział.
Stéphane Chazelas,
9

Jest to prawdopodobnie związane z extglobopcją powłoki. Jeśli go wyłączę, wzór wyświetli komunikat o błędzie:

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

Jeśli go włączę, to rzeczywiście wszystko pasuje. Strona man dokumentuje te wzorce, myślę, że są one powiązane:

   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

Nie widzę żadnej dokumentacji, która określałaby nawiasy bez wiodącej postaci. W każdym razie możesz obejść ten problem, cytując parens:

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

Użyj najpierw echolub, lsaby przetestować swój wzór, jeśli nie jesteś absolutnie pewien, że to działa :)

Martin von Wittich
źródło
FYI: {to (aparat ortodontyczny , to paren (lub okrągły nawias).
Mikel
Ach, dzięki. Nie jestem rodzimym językiem angielskim, więc mylę ich :)
Martin von Wittich
6
W języku brytyjskim: {= nawias klamrowy, (= nawias okrągły, [= nawias kwadratowy. W języku amerykańskim: {= klamra, (= paren, [= nawias. Trochę mylące. Jeśli kiedykolwiek chcesz sprawdzić, jak coś się nazywa, Jargon File - ASCII jest bardzo pomocny.
Mikel
4
@Mikel Dzięki, sprawdziłem również tutaj, więc teraz wiem o nawiasach kwiatowych i wiewiórczych !
W indyjskim angielskim {jest nawias kwiatowy, [jest nawias kwadratowy i (jest nawias okrągły lub częściej po prostu nawias. :-)
ShreevatsaR