当我在 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)