!(*.sh) 适用于命令行,但不适用于脚本

!(*.sh) 适用于命令行,但不适用于脚本

当我在 Ubuntu 上的终端中使用下面的代码时,它工作正常:

rm !(*.sh) -rf

但是如果我将相同的行代码放入 shell 脚本 ( clean.sh) 并从终端运行 shell 脚本,它会抛出错误,如下所示

clean.sh脚本:

#!/bin/bash
rm !(*.sh) -rf

我得到的错误:

./clean.sh: line 2: syntax error near unexpected token `('
./clean.sh: line 2: `rm !(*.sh) -rf'

你能帮我吗?

答案1

您需要开启extglob

shopt -s extglob

答案2

在 bash 中,某些图案默认情况下不启用,但可以通过设置选项来打开shopt。早期 Unix shell 中不存在的模式!(NOT-THIS)@(THIS|THAT)*(ZERO-OR-MORE)+(ONE-OR-MORE)?(OPTIONAL)后来在 ksh 中添加的,并且没有被 POSIX 标准化,默认情况下不被识别,您必须shopt -s extglob先运行。

您可以在命令行上使用这些模式;这表明您shopt -s extglob.bashrc.该文件只能由交互式 shell 读取,而不能由脚本读取。

(如果在 bash 开始运行脚本时设置了环境变量BASH_ENV,那么 bash 会读取它指定的文件,但我不建议依赖它,因为只有当BASH_ENV设置为您期望的值时,它才会使您的脚本工作,并且仅当您不更改它指向的文件时。)

只需包含shopt -s extglob在脚本顶部的#!/bin/bash行下方即可。

答案3

Shell 脚本方法

默认情况下,glob 在 BASH 脚本中不起作用(尽管您可以使用 打开它们shopt)。如果 shell 脚本由非 BASH 解释器运行,glob 可能根本无法工作。

您可以使用该命令获得相同的效果find,这就是我建议的做法(因为一旦您的需求增长,您可以拥有更多的控制权)。

试穿一下尺码:
find . -mindepth 1 -maxdepth 1 -not -iname "*.sh" -exec rm -rf {} \;

生成文件方法

您可以采取的另一种方法:

如果您正在做一些事后想要清理的事情,那么 Makefile 很可能是适合该工作的工具,而不是一堆 clean.sh、build.sh、install.sh 等。

如果您想确保您的配方始终按顺序发生,或者您并不总是想重新运行产生输出的配方,则尤其如此。

执行相同操作的简单 Makefile 如下所示:(
请注意,前面的空格rm需要是制表符,因为这就是 make 滚动的方式)

SOURCES := $(wildcard *.sh)
CLEAN_FILES := $(filter-out $(SOURCES),$(wildcard *))
CLEAN_FILES := $(filter-out Makefile,$(CLEAN_FILES))

build: $(SOURCES)
    YOUR_RECIPE_HERE

clean:
    rm -rf $(CLEAN_FILES)

相关内容