文件操作与模式匹配全解析
立即解锁
发布时间: 2025-08-25 00:17:17 阅读量: 1 订阅数: 10 

# 文件操作与模式匹配全解析
## 1. 文件操作中的输出重定向问题
在执行命令时,可能会遇到命令执行完成后,输出还未写入文件的情况。这是因为shell为每个重定向操作创建了额外的进程,用于将输出依次复制到各个文件中。shell会等待命令执行完毕后再执行下一个命令,但不会等待这些复制数据的进程完成,这些进程可能需要更多时间。
在zsh 4.2及更高版本中,对于在shell内部运行的命令,这个问题已得到修复。这是因为shell可以直接控制用于处理多输出的进程,并等待它们完成。对于外部程序(通过`PATH`环境变量查找的程序)以及旧版本的zsh,可以使用以下方法避免该问题:
```bash
{ ./mycommand } >record.txt >>allrecords.txt
```
这里的花括号指示shell运行一组命令(在本例中只有一个命令)。重定向操作应用于整个花括号内的命令,因此shell会等待输出写入文件后,再执行后续命令。
## 2. 空重定向作为快捷方式
zsh允许在不指定命令的情况下使用重定向(空重定向),作为写入输出或读取输入的快捷方式。示例如下:
```bash
zsh% >memo.txt
Reread the chapter on files before I go to bed.
<ctrl-d>
zsh% <memo.txt
Reread the chapter on files before I go to bed.
```
第一行是一个没有命令的输出重定向。zsh会自动添加`NULLCMD`变量指定的命令,默认情况下是`cat`,因此实际执行的是`cat >memo.txt`。这会将终端输入复制到文件中,使用特殊键`Ctrl-d`结束输入,表示文件结束。
第二行是一个没有命令的输入重定向。zsh会添加`READNULLCMD`变量指定的命令,默认情况下是`more`,因此实际执行的是`more <memo.txt`,这会在终端上显示`memo.txt`的内容。
需要注意的是,这种快捷方式是非标准的。其他shell(如bash)对于`<memo.txt`不会做任何处理,对于`>memo.txt`会创建一个空文件。建议仅在命令行中使用空重定向,在脚本和函数中始终完整输入命令名称。可以通过设置`sh_null_cmd`选项来关闭此功能。
## 3. 文件操作相关总结
以下是前面讨论的文件操作相关主题总结:
- 讨论了各种不同类型的文件,包括目录、普通文件、链接和特殊文件。
- 解释了使用shell和相关工具查找命令和其他文件的方法。
- 介绍了管理目录的各种方法,包括目录栈。在处理指向目录的符号链接时需要特别小心。
- 扩展了之前对重定向操作符`<`、`>`和`|`的解释,用于管理输入和输出,并介绍了一些相关概念,如文件描述符、Here文档和Here字符串。
- 演示了使用`tee`命令将输出复制到多个文件,以及zsh中的多输入输出重定向功能。
## 4. 模式匹配简介
许多初学者在日常工作中往往回避学习如何利用shell的模式匹配功能,尽管模式匹配是shell最强大的功能之一。实际上,无论你的知识水平如何,可能已经使用过一些模式,例如最常见的`*`通配符。使用模式进行文件匹配通常被shell程序员称为“globbing”,这个词源于“global”(如全局替换),它用一个术语概括了这个经常讨论的过程。
模式匹配不仅用于文件名匹配,shell还使用相同形式的模式进行其他操作,例如将字符串与模式进行比较。这在脚本和函数中非常有用。
模式匹配将分为bash和zsh都支持的模式、bash支持的模式以及zsh支持的模式。其中,zsh的模式匹配功能最为强大。虽然bash和zsh的高级模式语法不同,但有些功能是相似的。
需要注意的是,除非特别指定,shell会将目录名和其他文件名同等对待。因此,在提到“文件”时,通常指的是文件系统中具有名称的任何对象,包括目录。当指的是详细`ls -l`列表中第一列以`-`开头的基本文件类型时,通常会使用“普通文件”这个术语。
## 5. 基本通配符
在文件名中具有特殊含义的字符或字符集有时被称为操作符(也有其他叫法)。在本章中会遇到许多操作符,有些操作符仅在特定的shell中可用。几乎所有Unix风格的shell都支持简单的操作符,常见的基本通配符操作符总结如下表:
| 操作符 | 含义 |
| --- | --- |
| `*` | 匹配零个或多个字符,包括零个字符 |
| `?` | 匹配任意单个字符 |
| `[abc]` | 匹配方括号内的任意一个字符,如`a`、`b`或`c` |
| `[a-z]` | 匹配指定范围内的任意一个字符,如`a`到`z`之间的任意一个字符 |
| `[^a-z]` 或 `[!a-z]` | 匹配不在指定范围内的任意一个字符,如不在`a`到`z`之间的任意一个字符 |
需要记住的是,是shell负责扩展模式,而不是使用文件参数运行的程序。shell会将扩展后的文件名传递给程序,因此程序本身永远不会看到模式。(如果你的shell在Cygwin环境下运行,并且执行的是原生Windows命令,程序可能会在shell完成自身扩展后尝试扩展文件名中的模式。)
### 5.1 `*` 通配符
最基本的模式字符是`*`,在本章中称为“星号”。它可以匹配任意数量的字符,包括零个字符。例如,`file*`可以匹配以`file`开头的任何内容,包括`file`本身:
```bash
% ls
File Makefile file file.c file.txt
% echo *
File Makefile file file.c file.txt
% echo file*
file file.c file.txt
```
需要注意的是,显式指定的字母(如`file*`中的`f`)会被精确匹配,只要它不是操作符的一部分。字母的大小写也很重要。bash有一个`nocaseglob`选项,启用后
0
0
复制全文
相关推荐










