Parenthesis працює в bash shell, але не в bash script


11

Я можу запустити цю команду з мого командного рядка:

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

Для рекурсивного копіювання всього вмісту, folder крім підкаталогу, названого exclude-meв поточному каталозі. Це працює точно за призначенням. Однак мені це потрібно для роботи з написаним баш сценарієм, де я маю це:

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

Але коли я запускаю сценарій:

bash my-script.sh

Я отримую це:

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

І я втрачаю, чому це працює з командного рядка, але точно такий же рядок не працює в скрипті bash.

Відповіді:


11

Це тому, що синтаксис, який ви використовуєте, залежить від конкретної функції bash, яка за замовчуванням не активується для неінтерактивних оболонок (скриптів). Ви можете активувати його, додавши відповідну команду до свого сценарію:

## Enable extended globbing features
shopt -s extglob

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

Це відповідний розділ 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

Це вже другий раз, коли я знаходжу цю відповідь (так, погана пам'ять). Цього разу спробували запустити env > file1сценарій та виконати ./it, а потім env > file2і source it, сподіваючись, що я знайшов би різницю в envs, що не так. Як я можу програмно перерахувати всю різницю між двома оболонками (у цьому випадку інтерактивними проти неінтерактивними)?
Енріко Марія Де Анджеліс

@EnricoMariaDeAngelis див. Розділ Differentiate Interactive login та неінтерактивна невхідна оболонка та Як перевірити, чи оболонка є login / interactive / batch .
terdon

2

Додайте цей рядок біля вершини сценарію:

shopt -s extglob

!(...)є розширеною функцією відповідності шаблону, вам потрібно extglobвключити опцію, щоб використовувати його. Детальнішу інформацію див. У вбудованому магазині .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.