携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
前言
在本节中,我们将介绍如何递归地扫描目录以获取其中包含的所有文件,包括子目录中的所有文件。我们也可以搜索并匹配特定类型的文件,例如文本文件、音频文件或视频文件,也可以搜索某个特定文件。
Python 目录文件的扫描与搜索
目录的扫描通常是处理文件时的前置操作,用以检测指定目录下所有文件,以进行进一步处理。
创建文件及目录
为了能够保证测试环境的一致性,我们首先创建一个包含一些测试文件的测试目录:
$ mkdir test
$ touch test/test_file_1.txt
$ touch test/test_file_2.txt
$ touch test/test_file_6.pdf
$ mkdir test/sub_dir
$ touch test/sub_dir/test_file_3.txt
$ touch test/sub_dir/test_file_4.txt
$ touch test/sub_dir/test_file_5.pdf
为了进行测试,我们并未在文件中添加任何内容,也就是说所有文件都是空的,可以看到,在测试文件中有四个文件使用 .txt 扩展名,有两个具有 .pdf 扩展名。
对指定目录进行扫描和搜索
接下来,我们讲解如何对指定目录进行扫描和搜索。首先,进入创建的 test 目录:
$ cd test/
打印 test 目录和子目录中的所有文件名:
>>> import os
>>> for root, dirs, files in os.walk('.'):
... for file in files:
... print(file)
...
test_file_1.txt
test_file_6.pdf
test_file_2.txt
test_file_4.txt
test_file_3.txt
test_file_5.pdf
os.walk() 函数可以遍历整个目录及其下的所有子目录,并返回所有文件。对于每个目录,它返回一个包含目录、其下子目录以及文件的元组。
我们也可以打印文件的完整路径,只需要在文件名前加入文件的根目录:
>>> for root, dirs, files in os.walk('.'):
... for file in files:
... full_file_path = os.path.join(root, file)
... print(full_file_path)
...
./test_file_1.txt
./test_file_6.pdf
./test_file_2.txt
./sub_dir/test_file_4.txt
./sub_dir/test_file_3.txt
./sub_dir/test_file_5.pdf
其中 . 表示当前的工作目录,即 test/ 目录,os.path.join() 函数用于连接两个路径,例如示例中连接当前工作目录和文件名。
我们也可以仅打印指定类型的文件(以 .pdf 文件为例):
>>> for root, dirs, files in os.walk('.'):
... for file in files:
... if file.endswith('.pdf'):
... full_file_path = os.path.join(root, file)
... print(full_file_path)
...
./test_file_6.pdf
./sub_dir/test_file_5.pdf
或者,我们也可以仅打印包含偶数的文件:
>>> import re
>>> for root, dirs, files in os.walk('.'):
... for file in files:
... if re.search(r'[02468]',file):
... full_file_path = os.path.join(root, file)
... print(full_file_path)
...
./test_file_6.pdf
./test_file_2.txt
./sub_dir/test_file_4.txt
由于路径作为纯字符串返回,因此可以进行任何类型的过滤,包括使用正则表达式进行高级过滤。
os.path 模块更多实用函数
在 os.path 模块中除了以上功能外,还有许多非常实用的函数:
os.path.abspath(),返回文件的绝对路径>>> os.path.abspath('test_file_1.txt') '/home/brainiac/Documents/test/test_file_1.txt'os.path.split(),用于分割目录名和文件名>>> os.path.split(os.path.abspath('test_file_1.txt')) ('/home/brainiac/Documents/test', 'test_file_1.txt')os.path.exists(),返回文件系统上是否存在文件>>> os.path.exists('test_file_1.txt') True >>> os.path.exists('test_file_3.txt') False