Chybeta

Python中列目录相关函数/模块

测试环境:python 3.6.1 python 2.7.2
测试目录:cmspoc

os

os.listdir

语法:

1
os.listdir(path)

1
2
3
4
# python 3.6.1 python 2.7.2
>>> import os
>>> os.listdir("./")
['.ftpconfig', '.git', '.gitignore', 'cmspoc.py', 'data', 'lib', 'README.md', 'scripts', 'tty.gif', 'ttyrecord']

可以以列表(list)列出当前目录下的文件夹及其文件,但没有区分开。同时注意并没有把特殊目录.././作为结果返回。

可以利用os.path.isfile来判断是否为文件:

1
2
3
# python 3.6.1 python 2.7.2
>>> [ i for i in os.listdir("./") if os.path.isfile(i)]
['.ftpconfig', '.gitignore', 'cmspoc.py', 'README.md', 'tty.gif', 'ttyrecord']

可以利用os.path.isdir来判断是否为文件夹:

1
2
3
# python 3.6.1 python 2.7.2
>>> [ i for i in os.listdir("./") if os.path.isdir(i)]
['.git', 'data', 'lib', 'scripts']

也可以用来查找指定结尾(不一定是后缀)的文件:

1
2
3
4
>>> [i for i in os.listdir("./") if i.endswith("d")]
['README.md', 'ttyrecord']
>>> [i for i in os.listdir("./") if i.endswith(".py")]
['cmspoc.py']

os.walk

语法:

1
os.walk(top, topdown=True, onerror=None, followlinks=False)

os.walk可以进行文件遍历。它接受四个参数,但绝大部分情况下直接传入一个路径就可。它的返回值一个三元组(dirpath, dirnames, filenames)。dirpath是指当前目录路径,dirnames是当前目录下所有子目录的名字(包括...),filenames是指dirpath中的文件(即非文件夹)。

假设此时的目录在cmspoc的script目录中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
λ tree /F
卷 新加卷 的文件夹 PATH 列表
卷序列号为 000000DE 0CBE:322D
E:.
│ __init__.py
├─icms
│ v701_sqlinject_getadmin.py
│ __init__.py
└─phpcms
v960_fileupload_getshell.py
v960_sqlinject_getpasswd.py
__init__.py

则用for循环即可完成遍历:

1
2
3
4
5
6
7
# python 3.6.1 python 2.7.2
>>> for root, dirnames, filenames in os.walk('./'):
... print(root,dirnames,filenames)
...
./ ['icms', 'phpcms'] ['__init__.py']
./icms [] ['v701_sqlinject_getadmin.py', '__init__.py']
./phpcms [] ['v960_fileupload_getshell.py', 'v960_sqlinject_getpasswd.py', '__init__.py']

基于for循环遍历提取/过滤文件:

1
2
3
4
5
6
7
8
9
10
11
12
# python 3.6.1 python 2.7.2
>>> for root, dirnames, filenames in os.walk('./'):
... for f in filenames :
... if f.endswith(".py"):
... print(os.path.join(root,f))
...
./__init__.py
./icms/v701_sqlinject_getadmin.py
./icms/__init__.py
./phpcms/v960_fileupload_getshell.py
./phpcms/v960_sqlinject_getpasswd.py
./phpcms/__init__.py

os.scandir

从python3.5版本后有os.scandir(),能更快的遍历目录。更多介绍:os.scandir() function

1
2
3
4
5
6
7
8
9
10
11
12
# python 3.6.1
>>> for f in os.scandir():
... print(f)
...
<DirEntry '.ftpconfig'>
<DirEntry '.git'>
<DirEntry '.gitignore'>
<DirEntry 'cmspoc.py'>
<DirEntry 'data'>
<DirEntry 'lib'>
<DirEntry 'README.md'>
<DirEntry 'scripts'>

可以看到返回的是DirEntry对象,下面列一些简单的属性与方法。

仅打印出名字(name属性):

1
2
3
# python 3.6.1
>>> [f.name for f in os.scandir()]
['.ftpconfig', '.git', '.gitignore', 'cmspoc.py', 'data', 'lib', 'README.md', 'scripts','tty.gif', 'ttyrecord']

判断是否为文件:

1
2
3
# python 3.6.1
>>> [f.name for f in os.scandir() if f.is_file()]
['.ftpconfig', '.gitignore', 'cmspoc.py', 'README.md', 'tty.gif', 'ttyrecord']

判断是否为文件夹:

1
2
3
# python 3.6.1
>>> [f.name for f in os.scandir() if f.is_dir()]
['.git', 'data', 'lib', 'scripts']

glob

确切的说,glob模块不是来列目录的,是用来查找给定规则的文件路径名。查询所需的字符(规则)有三个:

  1. * 表示通配符,匹配零个或多个字符。
  2. ? 匹配一个字符。
  3. [] 匹配指定范围内的字符。

相关文档见这:python2.7python3.6

glob.glob

语法:

1
glob.glob(pathname)

可以使用绝对路径,配合*列出指定目录下所有文件:

1
2
3
4
# python 3.6.1 python 2.7.2
>>> import glob
>>> glob.glob(r"E:\cmsPoc\*")
['E:\\cmsPoc\\cmspoc.py', 'E:\\cmsPoc\\data', 'E:\\cmsPoc\\lib', 'E:\\cmsPoc\\README.md', 'E:\\cmsPoc\\scripts', 'E:\\cmsPoc\\tty.gif', 'E:\\cmsPoc\\ttyrecord']

也可以使用相对路径:

1
2
3
4
5
6
7
8
# python 3.6.1 python 2.7.2
# use *
>>> glob.glob(r"*")
['cmspoc.py', 'data', 'lib', 'README.md', 'scripts', 'tty.gif', 'ttyrecord']
# user ./*
>>> glob.glob(r"./*")
['.\\cmspoc.py', '.\\data', '.\\lib', '.\\README.md', '.\\scripts', '.\\tty.gif', '.\\ttyrecord']

可以查找满足符合规则的文件,比如查找py文件:

1
2
3
# python 3.6.1 python 2.7.2
>>> glob.glob(r"*.py")
['cmspoc.py']

在python3.5以上,glob.glob支持特殊通配符**和递归(recursive )操作,:

比如列出当前目录下所有的py文件:

1
2
>>> glob.glob(r"./**/*.py",recursive=True)
['.\\cmspoc.py', '.\\lib\\__init__.py', '.\\lib\\controllor\\controllor.py', '.\\lib\\controllor\\__init__.py', '.\\lib\\core\\common.py', '.\\lib\\core\\data.py', '.\\lib\\core\\datatype.py', '.\\lib\\core\\setting.py', '.\\lib\\core\\__init__.py', '.\\lib\\parse\\cmdline.py', '.\\lib\\parse\\__init__.py', '.\\lib\\plugin\\__init__.py', '.\\lib\\plugin\\crypto\\authcode.py', '.\\lib\\plugin\\crypto\\__init__.py', '.\\scripts\\__init__.py', '.\\scripts\\icms\\v701_sqlinject_getadmin.py', '.\\scripts\\icms\\__init__.py', '.\\scripts\\phpcms\\v960_fileupload_getshell.py', '.\\scripts\\phpcms\\v960_sqlinject_getpasswd.py', '.\\scripts\\phpcms\\__init__.py']

glob.iglob

iglob返回一个能生成与glob()结果相同的迭代器:

1
2
3
4
5
6
7
8
9
10
11
12
13
# python 3.6.1 python 2.7.2
>>> glob.iglob(r"./*")
<generator object _iglob at 0x00000096635ED150>
>>> for i in glob.iglob(r"./*"):
... print(i)
...
.\cmspoc.py
.\data
.\lib
.\README.md
.\scripts
.\tty.gif
.\ttyrecord

pathlib

pathlib在python3.4及其之后版本中默认继承了,python3.3之前的版本需要通过pip进行安装。

打印出当前目录(.)下的文件夹与文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# python 3.6.1
>>> import pathlib
>>> for p in pathlib.Path('.').iterdir():
... print(p)
...
.ftpconfig
.git
.gitignore
cmspoc.py
data
lib
README.md
scripts
tty.gif
ttyrecord

仅打印出当前目录(.)下的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# python 3.6.1
>>> for p in pathlib.Path('.').iterdir():
... if p.is_file():
... print(p)
...
.ftpconfig
.gitignore
cmspoc.py
README.md
tty.gif
ttyrecord
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]
[WindowsPath('.ftpconfig'), WindowsPath('.gitignore'), WindowsPath('cmspoc.py'), WindowsPath('README.md'), WindowsPath('tty.gif'), WindowsPath('ttyrecord')]

仅打印出当前目录(.)下的文件夹:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# python 3.6.1
>>> for p in pathlib.Path('.').iterdir():
... print(p)
...
.ftpconfig
.git
.gitignore
cmspoc.py
data
lib
README.md
scripts
tty.gif
ttyrecord
>>> [p for p in pathlib.Path('.').iterdir() if p.is_dir()]
[WindowsPath('.git'), WindowsPath('data'), WindowsPath('lib'), WindowsPath('scripts')]

Refference

微信扫码加入知识星球【漏洞百出】
chybeta WeChat Pay

点击图片放大,扫码知识星球【漏洞百出】