DOS Wildcard in PHP

该技巧仅适用于Windows环境
测试环境:

  • PHP 7.3.4
  • Windows 10

Description

http://avfisher.win/archives/tag/windows文件通配符分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
The following wildcard characters can be used in the pattern string.

Wildcard character Meaning

* (asterisk) Matches zero or more characters.

? (question mark) Matches a single character.

DOS_DOT Matches either a period or zero characters beyond the name
string.

DOS_QM Matches any single character or, upon encountering a period
or end of name string, advances the expression to the end of
the set of contiguous DOS_QMs.

DOS_STAR Matches zero or more characters until encountering and
matching the final . in the name.
1
2
3
4
5
6
//  The following constants provide addition meta characters to fully
// support the more obscure aspects of DOS wild card processing.

#define DOS_STAR (L'<')
#define DOS_QM (L'>')
#define DOS_DOT (L'"')

粗略来看<可以理解为通配符*>可以理解为通配符?"就只是.的另一种写法

但实际使用时还是有些区别

以下内容中输出的文件内容代表文件名

DOS_STAR <

<更类似于正则中的.*\.?

1
2
3
4
5
6
E:\[DATA EXPUNGED]\test>type "<"
bullshit
E:\[DATA EXPUNGED]\test>type "<a"
bullshit.a
E:\[DATA EXPUNGED]\test>type "<aaa"
999.txt.php.abc.aaa

在PHP中使用时则会存在一些区别

1
2
3
4
5
6
7
8
9
10
php > echo file_get_contents("<");
PHP Warning: file_get_contents(<): failed to open stream: Permission denied in php shell code on line 1

Warning: file_get_contents(<): failed to open stream: Permission denied in php shell code on line 1
php > echo file_get_contents("<t");
bullshit
php > echo file_get_contents("<a");
bullshit.a
php > echo file_get_contents("<aaa");
999.txt.php.abc.aaa

可以看到在函数file_get_contents()中不能仅使用DOS通配符<

DOS_QM >

>无法匹配.,且在超出文件名长度时会失效

1
2
3
4
5
6
7
8
E:\[DATA EXPUNGED]>type "1>>.>>>"
123.txt
E:\[DATA EXPUNGED]\test>type "1>>>>>>"
系统找不到指定的文件。
E:\[DATA EXPUNGED]\test>type "1>>.>>>>>"
123.txt
E:\[DATA EXPUNGED]\test>type ">>>>>>>>"
bullshit
1
2
3
4
5
6
7
8
9
10
11
12
php > echo file_get_contents(">>>.txt");
123.txt
php > echo file_get_contents(">>>>txt");
PHP Warning: file_get_contents(>>>>txt): failed to open stream: No such file or directory in php shell code on line 1

Warning: file_get_contents(>>>>txt): failed to open stream: No such file or directory in php shell code on line 1
php > echo file_get_contents(">>>.txt>>");
123.txt
php > echo file_get_contents(">>>>>>>>");
PHP Warning: file_get_contents(>>>>>>>>): failed to open stream: Permission denied in php shell code on line 1

Warning: file_get_contents(>>>>>>>>): failed to open stream: Permission denied in php shell code on line 1

可以看到在函数file_get_contents()中不能仅使用DOS通配符>

DOS_DOT "

这玩意可以当.来用,但是不知道为什么在CMD里面用不出来

1
2
php > echo file_get_contents("123\"txt");
123.txt

顺带一提
函数glob()可以使用通配符*?,但不能使用DOS通配符<>"
函数file_get_contents()可以使用DOS通配符<>",但不能使用通配符*?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
php > echo var_dump(glob("*aaa"));
array(1) {
[0]=>
string(19) "999.txt.php.abc.aaa"
}
php > echo var_dump(glob("999?txt.php.abc.aaa"));
array(1) {
[0]=>
string(19) "999.txt.php.abc.aaa"
}
php > echo var_dump(glob("<aaa"));
array(0) {
}
php > echo var_dump(glob(">>>.txt.php.abc.aaa"));
array(0) {
}
php > echo var_dump(glob("999\"txt.php.abc.aaa"));
array(0) {
}
php > echo var_dump(glob("999.txt.php.abc.aaa"));
array(1) {
[0]=>
string(19) "999.txt.php.abc.aaa"
}
1
2
3
4
5
6
7
8
9
10
php > echo file_get_contents("*aaa");
PHP Warning: file_get_contents(*aaa): failed to open stream: No error in php shell code on line 1

Warning: file_get_contents(*aaa): failed to open stream: No error in php shell code on line 1
php > echo file_get_contents("999?txt.php.abc.aaa");
PHP Warning: file_get_contents(999?txt.php.abc.aaa): failed to open stream: No error in php shell code on line 1

Warning: file_get_contents(999?txt.php.abc.aaa): failed to open stream: No error in php shell code on line 1
php > echo file_get_contents("999.txt.php.abc.aaa");
999.txt.php.abc.aaa