괄호는 bash 쉘 자체에서는 작동하지만 bash 스크립트에서는 작동하지 않습니다.

괄호는 bash 쉘 자체에서는 작동하지만 bash 스크립트에서는 작동하지 않습니다.

명령줄 프롬프트에서 다음 명령을 실행할 수 있습니다.

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

모든 것을 재귀적으로 복사folder 와는 별개로exclude-me현재 디렉터리 내의 명명된 하위 디렉터리입니다. 이것은 예상대로 정확하게 작동합니다. 그러나 내가 작성한 bash 스크립트에서 작동하려면 다음이 필요합니다.

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 스크립트에서는 똑같은 줄이 작동하지 않습니다.

답변1

이는 사용하는 구문이 활성화되지 않은 특정 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

귀하의 경우 bash에 대한 대화식 호출에서 이를 활성화하는 이유는 아마도 당신이 가지고 있거나 shopt -s extglob사용 ~/.bashrc하고 있기 때문일 것입니다.https://github.com/scop/bash-completion( bash-completion적어도 Debian 기반 운영 체제의 패키지에서 발견됨) via ~/.bashrc또는 /etc/bash.bashrcwhich를 포함함extglob초기화 시 활성화됨.

이러한 ksh 스타일 확장 glob 연산자는 빌드 시 bash 소스 코드의 스크립트 --disable-extended-glob에 전달하거나 .configure--enable-extended-glob-default

그러나 이는 extglobPOSIX 규정을 위반한다는 점에 유의하세요. 예를 들어 echo !(x)POSIX 언어 sh에서는 동작이 지정되지 않았지만

a='!(x)'
echo $a

출력은 현재 디렉터리의 파일 이름 목록이 아닌 !(x)기본값을 가정 해야 합니다. 단, 다음과 같이 사용하려는 빌드에서는 이 작업을 수행하면 안 됩니다. ksh에서는 이러한 연산자가 기본적으로 활성화되어 있지만 확장 시 인식되지 않습니다.$IFSxbashshX(...)

답변2

스크립트 상단 근처에 다음 줄을 추가합니다.

shopt -s extglob

!(...)확장된 패턴 일치 기능이므로 extglob사용하려면 활성화 옵션이 필요합니다. 바라보다내장 매장자세한 내용은.

관련 정보