文件通配符


Linux 启明道场.

才闯过几关,你可能就已经厌倦了反复输入这些文件路径。 好在 shell 有个解决办法:通配符匹配! 这就是本模块要学习的内容。

在执行你输入的命令之前,shell 会先对命令进行展开,通配符展开就是其中一种。 利用通配符,你可以引用文件,而不必逐个输入文件名或完整路径。 我们开始吧!


我们首先要学习的通配符是 *。 当参数中出现 * 字符时,shell 会把它视为“通配符”,并尝试用所有符合该模式的文件替换这个参数。 直接看例子更容易理解:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: file_*
Look: file_a file_b file_c

上面的通配符展开成了多个参数,不过它也完全可以只匹配一个文件。 例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ ls
file_a
hacker@dojo:~$ echo Look: file_*
Look: file_a

如果没有匹配到任何文件,shell 默认会保留通配符表达式,不做替换:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ ls
file_a
hacker@dojo:~$ echo Look: nope_*
Look: nope_*

* 可以匹配文件名中的任意部分,但不能匹配 /,也不能匹配文件名开头的 . 字符。 例如:

hacker@dojo:~$ echo ONE: /ho*/*ck*
ONE: /home/hacker
hacker@dojo:~$ echo TWO: /*/hacker
TWO: /home/hacker
hacker@dojo:~$ echo THREE: ../*
THREE: ../hacker

现在轮到你练习了! 从你的主目录出发,切换到 /challenge 目录,但要使用通配符,让传给 cd 的参数最多只有四个字符! 进入目录后,运行 /challenge/run 获取 flag!

接下来,我们来学习 ?。 当参数中出现 ? 字符时,shell 会把它视为单字符通配符。 它的用法与 * 类似,但只能匹配一个字符。 例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_cc
hacker@dojo:~$ ls
file_a	file_b	file_cc
hacker@dojo:~$ echo Look: file_?
Look: file_a file_b
hacker@dojo:~$ echo Look: file_??
Look: file_cc

现在自己试一试! 从你的主目录出发,切换到 /challenge 目录,但要用 ? 字符替换 c 和 l,作为传给 cd 的参数! 进入目录后,运行 /challenge/run 获取 flag!

接下来介绍 []。 方括号本质上是受限的 ?:[] 不会匹配任意字符,而是只匹配方括号内列出的某个字符。 例如,[pwn] 可以匹配字符 p、w 或 n。 来看一个例子:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: file_[ab]
Look: file_a file_b

在这里试试看! 我们在 /challenge/files 中放了一些文件。 将工作目录切换到 /challenge/files,然后运行 /challenge/run,只传入一个参数,使用方括号通配符将它展开为 file_b、file_a、file_s 和 file_h!

通配符匹配是以路径为单位进行的,所以带有通配符的参数也可以展开成完整路径。 例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: /home/hacker/file_[ab]
Look: /home/hacker/file_a /home/hacker/file_b

现在轮到你了。 我们又在 /challenge/files 中放了一些文件。 从你的主目录出发,运行 /challenge/run,只传入一个参数,使用方括号通配符将它展开为 file_b、file_a、file_s 和 file_h 这几个文件的绝对路径!

到目前为止,你每次只使用一个通配符,但其实还可以做得更多! Bash 支持在同一个词中展开多个通配符。 例如:

hacker@dojo:~$ cat /*fl*
pwn.college{YEAH}
hacker@dojo:~$

在上面的例子中,shell 会查找 / 下的所有文件:文件名可以以任意内容开头(也可以没有前缀),接着包含 f 和 l,最后以任意内容结尾(例如 ag,这样就组成了 flag)。

现在你来试试。 我们在 /challenge/files 中放了一些名字各不相同、寓意积极的文件。 用 cd 切换到该目录,运行 /challenge/run,只传入一个参数:一个简短的通配符表达式,长度不超过 3 个字符,其中包含两个 *,能够匹配所有包含字母 p 的文件名。

现在,把前几关学到的内容结合起来吧! 我们在 /challenge/files 中放了一些名字各不相同、寓意积极的文件。 用 cd 切换到该目录,运用你学过的通配符,写出一个长度不超过 6 个字符的表达式。将它作为单个参数传给 /challenge/run 时,它应该只匹配 "challenging"、"educational" 和 "pwning" 这三个文件!


提示: 仔细看看 /challenge/files 中的文件名。 有没有什么规律能帮助你构造通配符表达式?

有时,你希望在通配符匹配时排除某些文件! [] 正好能帮你做到这一点。 如果方括号中的第一个字符是 !,或者在较新版本的 bash 中是 ^,匹配规则就会取反:这组方括号会匹配未列出的字符。 例如:

hacker@dojo:~$ touch file_a
hacker@dojo:~$ touch file_b
hacker@dojo:~$ touch file_c
hacker@dojo:~$ ls
file_a	file_b	file_c
hacker@dojo:~$ echo Look: file_[!ab]
Look: file_c
hacker@dojo:~$ echo Look: file_[^ab]
Look: file_c
hacker@dojo:~$ echo Look: file_[ab]
Look: file_a file_b

有了这些知识,就去 /challenge/files,运行 /challenge/run,将所有不以 p、w 或 n 开头的文件作为参数传给它!

注意:在 bash 中,如果 ! 不是 [] 通配符表达式里的第一个字符,它还有另一种特殊含义。如果结果不符合你的预期,记得检查这一点!^ 没有这个问题,但它不兼容较旧的 shell。

用 * 减少命令行上的输入量确实很诱人,但也容易出错。 通配符可能展开成你原本没打算操作的文件,等你发现时,rm 命令也许已经在运行了! 谁都有可能犯这种错误。

如果你想指定一个明确的目标,Tab 补全是更安全的做法。 在 shell 中按下 Tab 键,它会尝试推断你接下来要输入的内容,并自动补全。 自动补全非常实用,本关将带你体验如何用它指定文件。

这一关已经将 flag 复制到 /challenge/pwncollege,你可以直接用 cat 读取该文件。 但你不能手动输入文件名:我们做了一些特别的处理,确保你必须用 Tab 补全。 试试看!

hacker@dojo:~$ ls /challenge
Dockerfile  pwncollege
hacker@dojo:~$ cat /challenge/pwncollege
cat: /challenge/pwncollege: No such file or directory
hacker@dojo:~$ cat /challenge/pwn<TAB>
pwn.college{HECK YEAH}
hacker@dojo:~$

按下 Tab 键后,文件名就会补全,你便能读取这个文件了。 祝你好运!

考虑下面这种情况:

hacker@dojo:~$ ls
flag  flamingo  flowers
hacker@dojo:~$ cat f<TAB>

有多个可选项! 这时会发生什么?

具体行为取决于你使用的 shell 及其配置。 默认情况下,bash 会补全到多个候选项开始出现差异的位置(本例中会补全为 fl)。 当你第二次按下 Tab 键时,它会列出这些候选项。 其他 shell 或配置则可能会让你依次切换候选项。

本关的 /challenge/files 目录中有许多以 pwncollege 开头的文件。 从 /challenge/files/p 这样的前缀开始使用 Tab 补全,一步步找到 flag!

Tab 补全不仅能用于文件! 你也可以用它补全命令。 本关有一条以 pwncollege 开头的命令,运行它就能获得 flag。 输入 pwncollege,然后按下 Tab 键自动补全吧!


注意: 任何命令都可以自动补全,但一定要小心:如果不仔细检查补全结果就贸然执行,一旦运行了错误的命令,可能会给你的 shell 环境造成严重破坏!


30天排行榜:

此排行榜反映本模块在道场上线后各挑战的解出情况。

排名 黑客 徽章 得分
#1 symbol ma'r'cen't 🐧 belt 1