Странное поведение функции Bash [дубликат]

Вопрос или проблема

Я пытался скопировать локальный каталог с исключениями в другое место в сценарии Bash и постоянно получал сообщение об ошибке синтаксиса. Я в конце концов создал минимальный пример, который воспроизводит мою проблему… что происходит только из функции.

Итак, это работает, как и ожидалось:

#!/usr/bin/env bash

rm -rf /tmp/adir/ && mkdir --parents /tmp/adir/
shopt -s extglob dotglob
cp -ar /some/dir/subdirectory/!(tests|.git) /tmp/adir/
shopt -u extglob dotglob

…но это не работает:

#!/usr/bin/env bash

a_function() {
  rm -rf /tmp/adir && mkdir --parents /tmp/adir
  shopt -s extglob dotglob
  cp -ar /some/dir/subdirectory/!(tests|.git) /tmp/adir
  shopt -u extglob dotglob
}

a_function

Второй вариант выдает ошибку синтаксиса:

./test.sh: line 6: syntax error near unexpected token `('
./test.sh: line 6: `    cp -ar /some/dir/subdirectory/!(tests|.git) /tmp/adir/'

Версия Bash: GNU bash, version 5.2.15(1)-release (x86_64-pc-linux-gnu)

Надеюсь, кто-то сможет помочь.

Параметр extglob должен быть установлен не только в строке, где он используется, но и в месте, где функция объявляется.

См. https://stackoverflow.com/q/65533232/1030675 для аналогичного вопроса и подробного ответа.

.

Ответ или решение

Необычное поведение функции Bash: Разбор проблем с extglob

При работе с Bash-скриптами иногда возникают специфические проблемы, которые могут вызвать путаницу. Одной из распространенных ситуаций является использование специального расширения шаблонов extglob, которое позволяет делать более гибкие сопоставления файлов и каталогов. Рассмотрим детально проблему, которая возникла при использовании extglob внутри функции Bash.

Проблема

Ваша проблема заключается в том, что при попытке выполнить команду копирования с использованием extglob внутри функции возникает синтаксическая ошибка. Ниже приведен минимальный пример, который демонстрирует эту ситуацию:

#!/usr/bin/env bash

a_function() {
  rm -rf /tmp/adir && mkdir --parents /tmp/adir
  shopt -s extglob dotglob
  cp -ar /some/dir/subdirectory/!(tests|.git) /tmp/adir
  shopt -u extglob dotglob
}

a_function

Ошибка, которую вы получаете, выглядит следующим образом:

./test.sh: line 6: syntax error near unexpected token `('
./test.sh: line 6: `    cp -ar /some/dir/subdirectory/!(tests|.git) /tmp/adir'

Причины проблемы

Суть проблемы заключается в том, что опции, такие как extglob, должны быть установлены не только во время выполнения команды, но и в контексте определения функции. Когда вы вызываете a_function, опции, активированные внутри функции, не действуют в контексте самого вызова функции, если они не были активированы заранее.

Решение

Для того чтобы ваше скриптовое решение работало должным образом, необходимо убедиться, что shopt устанавливается в области видимости, где вызывается функция. Вот несколько вариантов, как это можно реализовать:

  1. Установка shopt перед вызовом функции:

    Вы можете просто установить shopt вне функции, прежде чем вызывать её:

    #!/usr/bin/env bash
    
    shopt -s extglob dotglob
    
    a_function() {
     rm -rf /tmp/adir && mkdir --parents /tmp/adir
     cp -ar /some/dir/subdirectory/!(tests|.git) /tmp/adir
    }
    
    a_function
    
    shopt -u extglob dotglob
  2. Использование shopt внутри функции:

    Если вы хотите, чтобы опция действовала только внутри функции, вы можете сделать следующее:

    #!/usr/bin/env bash
    
    a_function() {
     shopt -s extglob dotglob
     rm -rf /tmp/adir && mkdir --parents /tmp/adir
     cp -ar /some/dir/subdirectory/!(tests|.git) /tmp/adir
     shopt -u extglob dotglob
    }
    
    a_function
  3. Комбинация подходов:

    Можно также комбинировать оба подхода, чтобы минимизировать риски и не оставлять extglob включённым во всем скрипте.

Заключение

Проблема с синтаксической ошибкой в вашем Bash-скрипте возникла из-за недостаточной области видимости активации extglob. Понимание особенностей работы функций Bash и механизмов активации расширенных глобов позволит вам избегать подобных ошибок в будущем. С помощью описанных выше решений вы сможете корректно реализовать функциональность, чтобы избежать неожиданных результатов при запуске ваших скриптов.

Оцените материал
Добавить комментарий

Капча загружается...