Bash

文件通配模式 !(*example) 在 bash 腳本中的行為與在 bash shell 中的行為不同

  • May 28, 2019

當直接粘貼到我的 bash 終端時,以下工作(我明確地呼叫 bash,bash 版本4.4.19(1)-release (x86_64-pc-linux-gnu):)

for filename in /home/dean/Downloads/!(*example).txt; do
   echo "${filename}"
done

此命令回顯文件名中沒有“example”的所有 txt 文件。

但是,當我將其轉換為名為 的腳本時temp.shchmod +x temp.sh並通過以下方式呼叫它./temp.sh

#!/usr/bin/env bash

for filename in /home/dean/Downloads/!(*example).txt; do
   echo "${filename}"
done

我收到以下錯誤:

dean@dean-thinkpad-p52s:~/Downloads$ ./temp.sh 
./temp.sh: line 3: syntax error near unexpected token `('
./temp.sh: line 3: `for filename in /home/dean/Downloads/!(*example).txt; do'

我無法理解這裡的問題。為什麼它在 shell 中執行我想要的操作,但在腳本中卻沒有。

編輯(回答panki的問題):

env在 shell/終端env中呼叫的時間和在 shell/腳本中呼叫的時間之間的區別:

dean@dean-thinkpad-p52s:~/Downloads$ diff example_myshell.txt example_called_script.txt 
5a6
> _=/usr/bin/env
36,37d36
< TERM=xterm-256color
< SHELL=/bin/bash
38a38,39
> SHELL=/bin/bash
> TERM=xterm-256color
45c46
< PYENV_SHELL=bash
---
> SHLVL=4
47c48
< SHLVL=3
---
> PYENV_SHELL=bash
61d61
< _=/usr/bin/env

!(...)Korn shell 擴展運算符僅在bash您打開該選項時可用extglob(預設為關閉)。

您可能已經extglob在互動式 shell 中打開了 via~/.bashrc或其他初始化文件,但請注意,在執行腳本時這些文件不是源文件,並且該選項不是從呼叫 shell 繼承的(除非BASHOPTS環境中的變數,但它會是把它放在那裡是個壞主意)。

顯式打開它

shopt -s extglob

在腳本的開頭應該可以工作。

請注意,shopt -s extglob唯一的效果從尚未解析的下一行開始。這意味著您不能使用shopt -s extgloblike set -f,僅在子外殼中打開擴展模式:

# this won't work
(
 shopt -s extglob
 echo !(no such file)
)

您必須執行以下操作:

(
 shopt -s extglob
 eval 'echo !(no such file)'
)

引用自:https://unix.stackexchange.com/questions/521287