文件匹配模式 !(*example) 在 bash 脚本中的行为与在 bash shell 中的行为不同

文件匹配模式 !(*example) 在 bash 脚本中的行为与在 bash shell 中的行为不同

当直接粘贴到我的 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 中完全按照我想要的方式执行,但在脚本中却不然。

编辑(回答潘基的问题):

env在shell/终端中调用when 与env在shell/script 中调用when之间的区别:

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

答案1

Korn shell 扩展运算符仅在您打开该选项时!(...)可用(默认情况下处于关闭状态)。bashextglob

您可能已extglob通过或其他初始化文件在交互式 shell 中打开~/.bashrc,但请注意,运行脚本时不会获取这些文件,并且该选项不是从调用 shell 继承的(除非BASHOPTS环境中的变量,但它将是把它放在那里是个坏主意)。

显式地打开它

shopt -s extglob

在脚本的开头应该可以工作。

请注意,shopt -s extglobonly 从尚未解析的下一行开始有效。这意味着您不能使用shopt -s extgloblikeset -f来仅在子 shell 中打开扩展模式:

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

你必须做类似的事情:

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

相关内容