MacOS의 확장된 glob 패턴의 구문 오류로 인해 bash `if` 블록 내용을 실행할 수 없습니다.

MacOS의 확장된 glob 패턴의 구문 오류로 인해 bash `if` 블록 내용을 실행할 수 없습니다.

간결한 버전:

내 Mac의 bash 블록 내에서 확장된 glob을 열 때 if전체 블록이 활성화된 후에도 블록 내에 포함된 확장된 glob 패턴에서 구문 오류로 인해 실패합니다. 다른 컴퓨터에서는 문제가 없습니다. 왜?

긴 버전:

if파일 전체에 다음과 같은 조건을 설정했습니다 .bashrc. 쉘 초기화 중에 실행되는 if다른 파일에도 유사한 명령문이 있습니다 . .*나중에 문제가 발생할 경우 파일이 재귀적으로 실행되는 것을 방지하기 위해 이렇게 합니다.

if [ -n "${_BASHRC_INIT}" ] ; then
export _BASHRC_INIT="True"

...
...
...

unset _BASHRC_INIT
fi

laa.bashrc확장된 glob에 의존하는 이 함수가 my에 정의되어 있습니다 . 함수를 정의하기 직전에 활성화합니다. 이 기능은 .*제외 및 일치하는 디렉토리의 .모든 파일을 표시합니다 ... ls별칭을 지정 했기 때문에 ls --color=auto파일 형식 색상도 표시되는데, grep. if블록 내부가 아닐 때 작동합니다 .

shopt -s extglob
laa() {
  if [[ $# -eq 1 ]]; then
    exec 3>&1                                 # Another file descriptor for this STDOUT
    _items=$(cd "${1}"; ls -d .!(|.)?* 1>&3)  # This requires extended glob
                                              # `shopt -s extglob` to enable
    exec 3>&-                                 # Close file descriptor
  elif [ $# -gt 1 ]; then
    exec 3>&1
    for i in $@; do
      _items=$(cd $i; echo "$i:" 1>&3; ls -d .!(|.)* 1>&3)
    done
    exec 3>&-
  else
    ls -d .!(|.)*
  fi
}

블록에 이 발췌문도 포함되어 있으면 블록에 포함된 명령 중 어떤 것도 if내 M1 Mac에서 실행될 수 없습니다 . 내 Windows PC의 WSL2(Debian)에서는 이 문제가 발생하지 않습니다. Mac은 bash 5.2.15Homebrew 및 WSL 실행이 설치된 상태로 실행됩니다 bash 5.1.4.

ls특히 다음 오류로 인해 명령이 실패합니다 .

bash: syntax error near unexpected token `('
bash: `    _items=$( cd "${1}"; ls -d .!(|.)?* 1>&3 )  # This requires extended glob'

입력 전에 실행하면 전체 if블록이 예상대로 실행됩니다. shopt -t extglob이것이 나의 현재 솔루션입니다. 그러나 이는 내 환경에서 설정하려는 규칙을 깨뜨립니다. 나는 .*내 컴퓨터에서 동일한 파일을 사용하려고 노력하는데, 이는 새 컴퓨터에서 일관된 환경을 빠르게 만드는 데도 도움이 됩니다.

블록 내용에 대한 추가 구문 검사의 원인은 무엇입니까 if?

답변1

여기에서는 KSH 스타일 확장 글로브를 완전히 피할 수 있습니다.- 예를 참조하세요.현재 디렉터리와 상위 디렉터리를 제외한 모든 숨겨진 파일을 전역적으로 표시하는 방법.


compat51아래6.12 셸 호환 모드

명령 대체 구문 분석은 확장 glob이 활성화된 것처럼 작동하므로(Shopt 내장 참조) extglob 패턴(예: 쉘 함수의 일부)이 포함된 명령 대체 구문 분석은 실패하지 않습니다. 이는 명령을 실행하고 단어 확장을 수행하기 전에 extglob을 활성화하려는 의도가 있다고 가정합니다. 명령이 실행될 때 extglob이 활성화되지 않으면 단어 확장 시 실패합니다.

예를 들어 고려하십시오.

#!/bin/bash

echo "$BASH_VERSION"

laa() {
  if [[ $# -eq 1 ]]; then
    exec 3>&1                                 # Another file descriptor for this STDOUT
    _items=$(cd "${1}"; ls -d .!(|.)?* 1>&3)  # This requires extended glob
                                              # `shopt -s extglob` to enable
    exec 3>&-                                 # Close file descriptor
  elif [ $# -gt 1 ]; then
    exec 3>&1
    for i in $@; do
      _items=$(cd $i; echo "$i:" 1>&3; ls -d .!(|.)* 1>&3)
    done
    exec 3>&-
  fi
}

shopt -s extglob
laa .

여기서는 extglob함수 정의 후 실행 전에 설정됩니다(함수가 .bashrc 파일에서 시작된 경우). bash 5.1에서는 작동합니다.

$ /bin/bash ./myscript
5.1.16(1)-release
.admins        .cache     .hardinfo  .parallel        .RData            .ssh                       .vboxclient-display-svga-x11.pid  .Xauthority       .zcompdump
.bash_history  .config    .lesshst   .password-store  .Rhistory         .sudo_as_admin_successful  .vboxclient-draganddrop.pid       .xinitrc          .zsh_history
.bash_logout   .dialogrc  .local     .profile         .selected_editor  .test_dot_folder           .vboxclient-seamless.pid          .xscreensaver     .zshrc
.bashrc        .gnupg     .mozilla   .python_history  .spectrum3d       .vboxclient-clipboard.pid  .wget-hsts                        .xsession-errors

5.2에서는 다음을 수행하지 않습니다.

$ ./src/bash-5.2.15/bash ./myscript
5.2.15(1)-release
./myscript: line 8: syntax error near unexpected token `('
./myscript: line 8: `    _items=$(cd "${1}"; ls -d .!(|.)?* 1>&3)  # This requires extended glob'

하지만, 행동외부명령 대체의 상황은 동일하므로 else블록을 추가한 후에는 다음과 같습니다.

#!/bin/bash

echo "$BASH_VERSION"

laa() {
  if [[ $# -eq 1 ]]; then
    exec 3>&1                                 # Another file descriptor for this STDOUT
    _items=$(cd "${1}"; ls -d .!(|.)?* 1>&3)  # This requires extended glob
                                              # `shopt -s extglob` to enable
    exec 3>&-                                 # Close file descriptor
  elif [ $# -gt 1 ]; then
    exec 3>&1
    for i in $@; do
      _items=$(cd $i; echo "$i:" 1>&3; ls -d .!(|.)* 1>&3)
    done
    exec 3>&-
  else
    ls -d .!(|.)*
  fi
}


shopt -s extglob
laa .

두 경우 모두 코드가 실패합니다. 5.2에서는 더 빠릅니다.

$ ./src/bash-5.2.15/bash ./myscript
5.2.15(1)-release
./myscript: line 8: syntax error near unexpected token `('
./myscript: line 8: `    _items=$(cd "${1}"; ls -d .!(|.)?* 1>&3)  # This requires extended glob'
$ 
$ /bin/bash ./myscript
5.1.16(1)-release
./myscript: line 18: syntax error near unexpected token `('
./myscript: line 18: `    ls -d .!(|.)*'

bash 5.1 동작을 사용해야 하는 경우 BASH_COMPAT=51.bashrc 파일의 함수 정의 전에 이를 설정할 수 있습니다.

관련 정보