我正在学习 shell 命令并遇到了短标签,例如[0-9]、[[:digit:]] 等。作为概念证明,我尝试使用 rm 命令删除所有文件(我知道它不是一个很好的做法,但我想了解事情是如何运作的),就像这样
rm [0-9].txt
目录中有两个文件 0.txt 和 9.txt ,它删除了文件 0.txt 和 9.txt 。我猜测表达式 [0-9] 被扩展然后读为 0.txt 1.txt 2 .txt ....但是,当您仅尝试 rm 5.txt 并且该文件不存在时,会引发错误。
有人请告诉我速记命令与 rm 或 ls 一起使用时如何工作。
答案1
这就是所谓的通配(链接到 bash 文档,但这并非特定于 bash)。
当您运行时rm [0-9].txt
,shell 会扩展[0-9].txt
到目录中与该模式匹配的文件列表。然后该列表作为参数传递给rm
(每个文件作为单独的参数)。
所以不,shell 不会将其扩展为0.txt 1.txt ... 9.txt
,它会查看匹配的文件。
为什么你只运行rm 5.txt
,没有要扩展的 glob 模式,因此参数按原样传递给rm
,它注意到该文件不存在并抱怨。
尝试其他方法:相同的命令rm [0-9].txt
,但在一个目录中不有与该模式匹配的任何文件。您会再次注意到rm
抱怨,但这一次它会说:
rm: cannot remove '[0-9].txt': No such file or directory
如果 glob 模式不匹配任何内容,就会发生这种情况(无论如何默认情况下):shell 不会扩展它并保持不变。
此类模式匹配的 POSIX 参考:模式匹配表示法。
答案2
不要用 测试rm
,用 测试echo
!
[0-9].txt
是通配符模式(也称为 glob)。它扩展为现有文件名的列表。在 glob 模式中,您可以使用三种通配符:
- 该字符
*
匹配任何字符序列(包括空序列)。 - 该字符
?
与任意一个字符匹配。 - 括号表达式
[…]
匹配出现在括号内的任一字符。
[0-9]
是 的快捷方式[0123456789]
。您可以-
在括号内的两个字符之间使用 a 来表示这两个字符以及其间的任何两个字符。例如,[0-9a-z_]
匹配数字、小写字母或下划线。
还有一些关于括号的规则,我在这里不再提及。
重申一下,所有这些构造仅匹配现有文件。如果没有具有该名称的文件,[0-9].txt
则不会扩展为,也不会扩展为如果没有具有该名称的文件,则不会扩展5.txt
为更多。*.txt
dfiojedfoi.txt
例子:
$ ls
0.txt 10.txt 1a.txt 9.txt hello.txt world.txt
$ echo [0-9].txt
0.txt 9.txt
$ echo [0-9][0-9].txt
10.txt
$ echo [0-9][0-9][0-9].txt
[0-9][0-9][0-9].txt
$ echo [0-9]?.txt
1a.txt 10.txt
$ echo [10-19].txt
0.txt 9.txt
$ echo *.txt
0.txt 1a.txt 9.txt 10.txt hello.txt world.txt
$ echo *l*
hello.txt world.txt
echo [0-9][0-9][0-9].txt
只是重复该模式,因为没有匹配的文件。确保您理解为什么[10-19].txt
只匹配这两个文件而不匹配10.txt
或19.txt
。