Nawiasy działają w samej powłoce bash, ale nie w skrypcie bash

11

Mogę uruchomić to polecenie z wiersza polecenia:

cp -r folder/!(exclude-me) ./

Aby rekurencyjnie skopiować całą zawartość z folder wyjątkiem podanego podkatalogu exclude-medo bieżącego katalogu. Działa to dokładnie zgodnie z przeznaczeniem. Potrzebuję tego jednak do pracy w skrypcie bash, który napisałem, gdzie mam to:

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./
  rm -rf folder
fi

Ale kiedy uruchamiam skrypt:

bash my-script.sh

Rozumiem:

my-script.sh: line 30: syntax error near unexpected token `('
my-script.sh: line 30: `  cp -r folder/!(exclude-me) ./'

Nie wiem, dlaczego działa z wiersza polecenia, ale dokładnie ta sama linia nie działa w skrypcie bash.

nzifnab
źródło

Odpowiedzi:

11

Jest tak, ponieważ używana składnia zależy od konkretnej funkcji bash, która nie jest domyślnie aktywowana dla nieinteraktywnych powłok (skryptów). Możesz go aktywować, dodając odpowiednie polecenie do skryptu:

## Enable extended globbing features
shopt -s extglob

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./
  rm -rf folder
fi

To jest odpowiedni rozdział man bash:

   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
terdon
źródło
Po raz drugi znajduję tę odpowiedź (tak, zła pamięć). Tym razem starał się uruchomić env > file1w skrypcie i wykonywać ./it, a następnie env > file2i source it, w nadziei, że znalazłem różnicę w envs, co nie jest prawdą. Jak mogę programowo wymienić wszystkie różnice między dwiema powłokami (w tym przypadku interaktywne vs nieinteraktywne)?
Enrico Maria De Angelis,
2

Dodaj tę linię u góry skryptu:

shopt -s extglob

!(...)jest rozszerzoną funkcją dopasowania wzorca, musisz extglobwłączyć opcję, aby z niej korzystać. Zobacz wbudowane shopt, aby uzyskać więcej informacji.

Cuonglm
źródło