1. 通配符定义
通配符是指在操作系统中,用于代替其它字符或字符串的符号,可以匹配符合相应规则的文件或目录。即:可以使用通配符代表许多同种格式的文件。如:*.o 表示所有的.o文件
在命令行中,常用的通配符有以下几种:
1.* (星号):表示任意长度的任意字符(包括空字符),可以出现在文件名中的任意位置。
2. ? (问号):表示一个任意字符,且只能替代一个字符。
3. [] (中括号):可匹配其中某个指定字符,可以出现在文件名中的任意位置,如 [abc] 表示可以匹配 a、b、c 中任意一个字符。
4. {} (花括号):可使用逗号隔开的多个字符串中的一个。例如 {a,b,c} 表示可以匹配字符串 a、b、c 中的任意一个。
这些通配符的使用方法类似,都是在命令行中直接使用。使用通配符可以方便地批量操作文件,如删除、复制等。
2. ‘%’并不是通配符
首先说说‘%’,在Linux中,`%`不是通配符,而是一种特殊的替换符号,在一些命令或脚本中可以使用。
在`make`命令中,`%`可以匹配任意字符序列,用于表示规则中的通配符,如`%.o`可以匹配所有以`.o`为后缀的文件名。这样就可以很方便地使用单一规则来生成多个目标文件。
例如,在下面的规则中,`%.o`表示所有的`.o`文件:
```
%.o : %.c
gcc -c $<
```
其中,`$<`代表依赖项中第一个文件的名称,也就是与这个`.o`文件对应的`.c`文件。这样,在执行这条规则时,`make`会自动将所有符合规则的`.o`文件依次生成。
需要注意的是,`.`表示当前目录,所以`%.o`也可以匹配当前目录下的所有`.o`文件。但是,如果有多个目录中都存在`.o`文件,那么`%.o`只能匹配在当前目录下的`.o`文件,不能匹配所有的`.o`文件。在这种情况下,需要使用相应的通配符来匹配不同目录下的`.o`文件。
3. ‘%’与‘*’的区别
%.o
和*.o
都可以匹配系统中的.o
文件,但是匹配的方式有所不同。
%.o
只能匹配当前目录下的.o
文件,因为它是用于make
命令中的通配符,用于表示规则中的通配符,如%.o
可以匹配所有以.o
为后缀的文件名,但是只能匹配当前目录下的文件。
而*.o
则可以匹配系统中所有.o
文件,因为它是Shell中的通配符,可以匹配所有符合条件的文件,不限于当前目录。
例如,如果你希望查找系统中所有以.o
为后缀的文件,可以使用以下命令:
find / -name "*.o"
这个命令可以在整个文件系统中查找所有符合条件的.o
文件,并打印出它们的绝对路径。
需要注意的是,使用*
等通配符,一定要小心使用,不要误删除或覆盖了重要文件。
4. 下面这个讨论是转载的,对原文做了一定的删改,可以用作参考,来源:Makefile中的%标记和系统通配符*的区别 - 大火人 - 博客园 (cnblogs.com)
Makefile中的%标记和系统通配符*的区别在于,*是应用在系统中的,%是应用在这个Makefile文件中的。
(本文的测试环境是Windows7下使用MinGW提供的make.exe)
例如,如果你想编译一个文件夹下的所有.c文件,你可能会这样写:
%.o:%.c
gcc -o $@ $<
但是如果整个文件只有这两行的话,就会出现这样的错误:
Make: *** target not found. stop.
要知道原因,我们先来看看另一个makefile的运行过程,例如有Makefile如下:
test1.o:test1.c
gcc -o test1.o test1.c
test2.o:test2.c
gcc -o test2.o test2.c
all:test1.o test2.o
如果没有指定输出项目的时候Make会自动找到makefile中第一个目标中没有通配符的目标进行构造,所以步骤是:
- 构造all,发现需要test1.o和test2.o
- 这个时候他就会在Makefile文件中找到目标能匹配test1.o和test2.o的规则。
- 找到test1.o的规则并且知道test1.c存在,运行下面的命令。
- 同步骤三构造出test2.o
- 现在构造all的源文件已经齐全,构建all
其中最重要的是第2步。
Makefile的通配符是在带着目的(如“寻找test1.o”)的时候才会把他要寻找的目标套用通配符%中。
所以通配符%的意思是:
- 我要找test1.o的构造规则,看看Makefile中那个规则符合。
- 然后找到了%.o:%.c,
- 来套一下来套一下:
- %.o 和我要找的 test1.o 匹配
- 套上了,得到%=test1。
- 所以在后面的%.c就表示test1.c了。
- OK进行构造
而通配符*的意思是:
- 我不知道目标的名字,系统该目录下中所有后缀为.c的文件都是我要找的。
- 然后遍历目录的文件,看是否匹配。找出所有匹配的项目。
所以虽然连个符号的意思有点沾边,但是他们的工作方式时完全不一样。
现在知道了为什么文件中只有
%.o:%.c
gcc -o $@ $<
会找不到目标了吧。因为没有-f参数时Make会自动找到makefile中第一个目标中没有通配符的目标进行构造,所以就等于找不到目标了。它的意思并不会自动把文件中所有的文件都编译。
所以正确的代码应该是:
all:$(subst .c,.o,$(wildcard *.c))
%.o:%.c
gcc -o $@ $<
这才是把目录下所有文件都编译的命令。