Bash扩展模式匹配:shopt -s extglob 详解

shopt -s extglob
`shopt -s extglob` 是一个 Bash shell 命令,用于开启 Bash 的扩展模式匹配功能。`shopt` 是一个内置命令,用于设置和取消 Bash 的可选项特性。`-s` 参数表示开启(set)某个选项,而 `extglob` 是一个选项名称,代表扩展的模式匹配。

### 详细解释:

1. **shopt**:Bash 的内置命令,用于改变和查看 shell 的可选行为。

2. **-s**:这个参数告诉 `shopt` 命令要开启(set)后面指定的选项。

3. **extglob**:这是 `shopt` 命令的一个选项,用于开启扩展的模式匹配。在默认情况下,Bash 使用基本的模式匹配(globbing),它只支持简单的模式如 `*` 和 `?`。开启 `extglob` 后,Bash 会支持更多的模式匹配符号,如 `@`、`+`、`!` 等。

### 扩展模式匹配符号:

- `?(pattern-list)`:匹配零次或一次 `pattern-list` 中的模式。
- `*(pattern-list)`:匹配零次或多次 `pattern-list` 中的模式。
- `+(pattern-list)`:匹配一次或多次 `pattern-list` 中的模式。
- `@(pattern-list)`:匹配 `pattern-list` 中的一个模式。
- `!(pattern-list)`:匹配除了 `pattern-list` 中的模式之外的任何模式。

### 举例说明:

假设你有一个目录,里面有以下文件:
file1.txt
file2.txt
file3.log
file4.log
1. **基本模式匹配**:
ls *.txt
这将匹配所有以 `.txt` 结尾的文件,输出:

                
<think>我们想要删除当前目录中除了指定文件夹(假设为`my_folder`)以外的所有文件和文件夹。注意:不能删除`my_folder`本身,同时要保留`my_folder`里的内容。另外,我们也要注意不要删除当前目录下的隐藏文件(以点开头的文件)吗?但通常用户可能只关心非隐藏的文件和文件夹,但根据需求,我们可能希望只保留指定文件夹(包括其隐藏文件也会保留),而删除其他所有文件和文件夹(包括隐藏文件?)。所以具体需求需要明确。不过,用户的问题描述是“删除指定文件夹外的所有文件,同时保留该文件夹”。这里我们需要明确:-用户可能希望保留指定文件夹(及其内部所有内容),然后删除当前目录下其余所有内容(包括文件和文件夹,包括隐藏的?)常见做法:1.使用`find`命令:可以排除指定目录,然后删除其他所有文件和目录。2.使用`rsync`:有点复杂,不太常用在这种场景。3.使用`rm-rf`配合通配符:但通配符会跳过隐藏文件和文件夹,所以需要额外处理隐藏文件。但是,这里有一个很危险的情况:如果当前目录就是根目录或者用户的家目录,那么执行这个命令将导致灾难性的后果。因此,我们需要确保命令在正确的目录执行,并且指定目录名称正确。我们假设用户在当前目录下操作,并且要保留的目录名为`my_folder`。方案1(使用find命令):我们可以使用find查找当前目录下的所有文件和目录(除了要保留的目录以及它里面的内容),然后删除。注意:不要删除当前目录本身(即`.`),所以我们不能删除`.`,同时要排除的目录我们要用`-path`匹配。命令如下:```bashfind.-maxdepth1!-path'.'!-path'./my_folder'!-path'./my_folder/*'-execrm-rf{}+```但上述命令有问题:`-path'./my_folder/*'`在`-maxdepth1`的情况下不会匹配子目录内部,所以可以省略。同时,我们只需要匹配当前目录下的文件和目录,排除`my_folder`本身。因此,可以简化为:```bashfind.-maxdepth1!-name'my_folder'!-name'.'|xargsrm-rf```但这个命令会跳过隐藏文件吗?不会,find会找到所有文件。而且这样删除了当前目录下的所有非`my_folder`的文件和目录(包括隐藏文件和目录),但注意`.`和`..`不会被包括,因为`-maxdepth1`下不会返回上级目录,而`.`被我们排除了。但是,这个命令有一个潜在风险:如果文件或目录名包含空格或其他特殊字符,可能会出现问题。因此,我们可以使用`-print0`和`xargs-0`来处理:```bashfind.-maxdepth1!-name'my_folder'!-name'.'-print0|xargs-0rm-rf```方案2(更简单但需要谨慎):移动要保留的目录到父目录,然后删除整个目录,再把保留的目录移动回来?```bash#假设当前目录为当前路径mvmy_folder/tmp/#先移到临时位置rm-rf*#删除当前目录下所有文件和目录(非隐藏)rm-rf.[^.].??*#删除所有隐藏文件和目录(除了.和..)但这样可能会误删重要隐藏文件,比如.git等,所以要小心#然后把my_folder移回来mv/tmp/my_folder.```这种方法有点暴力,而且不能保证删除所有隐藏文件(因为上面两个命令不能匹配所有隐藏文件,例如三个点开头的文件?),同时需要临时空间,不推荐。方案3:另一种使用find的方式(更安全且高效):```bashfind.-mindepth1-maxdepth1!-name'my_folder'-execrm-rf{}+```解释:-`-mindepth1`:排除当前目录(`.`)-`-maxdepth1`:只搜索当前目录-`!-name'my_folder'`:排除名为`my_folder`的目录(或文件)这样,其他所有文件和目录都会被删除(包括隐藏的)。注意:这个命令会立即删除文件,请确保当前目录不在其他重要位置。也可以先运行`find.-mindepth1-maxdepth1!-name'my_folder'`来查看将要删除哪些文件。但是,这里有一个重要的注意事项:如果要保留的目录是一个链接(symboliclink)?那么`-name`匹配的是链接的名字,而不是它指向的目录。所以如果你有一个名为`my_folder`的链接,指向其他地方,那么这条命令不会删除这个链接,但会删除链接指向的实际目录吗?不会,rm-rf一个链接只是删除链接本身,不会影响目标。所以这可以接受。因此,我们推荐方案3的find命令。如果用户希望保留多个目录怎么办?这里用户只要求保留一个,所以我们按一个来处理。命令:```bashfind.-mindepth1-maxdepth1!-name'要保留的文件夹名'-execrm-rf{}+```例如,要保留名为`keep`的文件夹:```bashfind.-mindepth1-maxdepth1!-name'keep'-execrm-rf{}+```警告:这条命令非常危险!请确保:1.当前目录就是你要清理的目录,并且没有其他重要文件。2.要保留的文件夹名输入正确。另外,在执行之前,可以先看一下要删除的文件列表:```bashfind.-mindepth1-maxdepth1!-name'keep'```如果用户要求保留多个目录,那么可以扩展为:```bashfind.-mindepth1-maxdepth1!-name'dir1'!-name'dir2'-execrm-rf{}+```但是,用户的问题中只要求保留一个文件夹。注意:在Linux中,文件名是区分大小写的。所以`!-name'keep'`不会排除名为`Keep`的文件夹。最后,如果用户想要在脚本中执行,请务必先测试。因此,我们最终给出的解决方案是:**步骤1:**进入目标目录(如果需要清理的目录不是当前目录,则先cd过去)。**步骤2:**运行以下命令(假设要保留的目录名为`my_folder`):```bashfind.-mindepth1-maxdepth1!-name'my_folder'-execrm-rf{}+```但是,请注意,如果`my_folder`是一个文件,那么它也会被保留,而其他文件被删除。所以请确保`my_folder`确实是一个目录。如果用户想要保留的文件夹名包含空格或其他特殊字符,需要确保正确转义。在命令中直接写名字,并用引号括起来(如上面所示)可以避免空格问题,但如果名字包含通配符,则可能需要转义。不过,`-name`参数中的字符串是字面匹配,除了方括号等需要转义,一般不需要。如果名字非常特殊,可以使用`-iname`进行不区分大小写匹配,但这里我们使用精确匹配。另外,如果要保留多个目录,可以这样:```bashfind.-mindepth1-maxdepth1!-name'folder1'!-name'folder2'-execrm-rf{}+```最后,我们生成相关问题:相关问题:1.如何删除除特定文件外的所有文件?2.如何删除当前目录中的所有隐藏文件?3.如何排除多个目录进行删除?4.如何在脚本中安全地删除文件和目录?</think> ### 如何删除指定文件夹外的所有文件同时保留该文件夹 要安全删除当前目录中**除特定文件夹外**的所有文件和子目录,请按以下步骤操作(以保留名为`keep_folder`的文件夹为例): #### 推荐方法:使用 `find` 命令 ```bash # 删除当前目录下的所有内容,但保留 keep_folder 及其内容 find . -maxdepth 1 ! -path '.' ! -path './keep_folder' ! -path './keep_folder/*' -exec rm -rf {} + ``` #### 方法详解 1. **`find .`** 从当前目录开始搜索 2. **`-maxdepth 1`** 仅处理当前目录(不进入子目录) 3. **排除规则** - `! -path '.'` → 排除当前目录本身 - `! -path './keep_folder'` → 排除要保留的文件夹 - `! -path './keep_folder/*'` → 排除保留文件夹内的内容 4. **`-exec rm -rf {} +`** 对匹配项执行递归强制删除 #### 安全验证步骤 1. 先预览将被删除的文件(**不实际执行删除**): ```bash find . -maxdepth 1 ! -path '.' ! -path './keep_folder' ! -path './keep_folder/*' ``` 2. 确认输出结果无误后再执行实际删除 #### 重要注意事项 1. **路径规范** - 命令中的 `./keep_folder` 必须与目标文件夹的**实际路径完全匹配** - 若保留文件夹不在当前目录,需使用绝对路径如 `/home/user/keep_folder` 2. **隐藏文件处理** 上述命令会删除所有隐藏文件(以`.`开头的文件)。若需保留隐藏文件,添加额外排除规则: ```bash find . -maxdepth 1 ! -path '.' ! -path './keep_folder*' ! -name '.*' ``` 3. **权限问题** 若提示权限不足,在命令前加 `sudo`: ```bash sudo find ... ``` --- ### 典型错误案例与修复 #### 错误:使用通配符 `*` ```bash # 危险!会跳过隐藏文件,且可能因路径包含空格导致误删 rm -rf !(keep_folder) ``` #### 修复方案 1. **启用扩展通配符**(需先执行): ```bash shopt -s extglob ``` 2. **正确排除操作**: ```bash rm -rf !(keep_folder) # 仅保留指定文件夹 rm -rf !(@(dir1|dir2)) # 保留多个文件夹[^3] ``` --- ### 操作流程总结 ```mermaid graph TD A[开始] --> B[cd 到目标目录] B --> C[预览将被删除的文件] C --> D{确认结果正确?} D -->|是| E[执行删除命令] D -->|否| F[调整路径/排除规则] E --> G[确认 keep_folder 保留成功] F --> C G --> H[完成] ``` > ⚠️ **终极警告** > 1. 执行删除前**务必备份重要数据** > 2. 避免在根目录(`/`)或家目录(`~`)执行 > 3. 使用 `-i` 参数可交互式确认每个删除操作 > ```bash > find ... -exec rm -rfi {} + > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值