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

Dea*_*ton 5 bash shell-script wildcards bash-expansion

当直接粘贴到我的bash终端下工作(我明确地调用庆典,庆典版本:4.4.19(1)-release (x86_64-pc-linux-gnu)

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

此命令回显所有文件名中没有“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

Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

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'
Run Code Online (Sandbox Code Playgroud)

我不明白这里的问题。为什么它在 shell 中做我想要的,而不是在脚本中。

编辑(回答panki的问题):

env在 shell/终端env中调用when 和在 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

Run Code Online (Sandbox Code Playgroud)

mos*_*svy 13

!(...)Korn shell的扩展运算器只适用于bash当您打开extglob的选项(这是默认关闭)。

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

显式打开它

shopt -s extglob
Run Code Online (Sandbox Code Playgroud)

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

请注意,shopt -s extglob只有从尚未解析的下一行开始才有效。这意味着您不能使用shopt -s extgloblike set -f, 仅在子外壳中打开扩展模式:

# this won't work
(
  shopt -s extglob
  echo !(no such file)
)
Run Code Online (Sandbox Code Playgroud)

您必须执行以下操作:

(
  shopt -s extglob
  eval 'echo !(no such file)'
)
Run Code Online (Sandbox Code Playgroud)

  • 这是 bash 中的一个错误。`shopt -s extglob` 仅从下一行开始生效。除了将它们放在单独的行上之外,您真的无能为力。 (2认同)
  • 是的,你不能在函数中打开它,因为函数被解析为一个单元,就像我的例子中的 `(...)` 子shell。(顺便说一句,无论如何,`shopt` 选项与`set` 选项不同,不能通过`local -` 设置为函数的本地选项)。另一个类似的怪癖/错误是使用 `failglob` 选项——失败的 glob 会破坏整个行/解析单元,而不仅仅是它使用的命令,甚至 `eval` 也不会帮助它;-) `( shopt -s failglob; eval 'echo hehe*'; echo DONE)` (2认同)