使用Python实现关键字搜索文件

让我们通过20行python代码实现一个简单的关键字搜索工具

目录遍历

首先我们来看如何实现目录遍历

目录遍历的过程很简单:

  1. 将目标路径作为当前目录
  2. 罗列出当前目录下的所有内容
  3. 判断每一个目标是否是文件夹。
  4. 如果是,进入该文件夹搜索(将文件夹路径改为当前路径,多级目录在此处会循环)

为什么我们要使用递归,与for对已知大小的列表的遍历相比,递归更适合与那些确定开始结束条件而过程不确定的情况。我们将初始路径设为起点,将目录下没有其他目录可以进入的情况设为终点

让我们来看如何通过递归的方式来遍历某个路径下的所有内容

1
2
3
4
5
6
7
def search(path):
content = os.listdir(path)
for each in content:
each_path = path + os.sep + each
if os.path.isdir(each_path):
search(each_path)
print(each_path)#测试输出
  • 第1行:首先我们先定义一个search函数,参数path是接收的路径
  • 第2行:os.listdir(path) 将path路径下的所有(文件/文件夹)作为一个列表返回
  • 第3行:使用for循环遍历当前目录
  • 第4行:构建当前目录下文件的完整目录(当前目录/文件名称),os.sep为当前操作系统的分隔符
  • 第5行:判断这个目标是否是文件夹
  • 第6行:如果是,把这个文件夹作为新的路径像刚才那样再来一遍
  • 第7行:最后在循环的后面我们加一个print来看看输出了什么

来看我们的测试目录test的结构

1
2
3
4
5
6
7
8
9
10
11
12
13
test
├── a
│   ├── a
│   ├── b
│   └── c
│   └── file.md
├── b
│   ├── a
│   └── b
│   └── target.py
├── c
│   └── a
└── d

测试,进入test目录并使用os.getcwd()返回当前路径:

1
>>> search(os.getcwd())

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
/home/Jkob/Github/test/b/b/target.py
/home/Jkob/Github/test/b/b
/home/Jkob/Github/test/b/a
/home/Jkob/Github/test/b
/home/Jkob/Github/test/a/b
/home/Jkob/Github/test/a/a
/home/Jkob/Github/test/a/c/file.md
/home/Jkob/Github/test/a/c
/home/Jkob/Github/test/a
/home/Jkob/Github/test/d
/home/Jkob/Github/test/c/a
/home/Jkob/Github/test/c

目录的遍历有什么用呢,我们可以添加条件来(搜索/操作)目录下所有符合条件的文件

文件名搜索

我们来对刚刚的函数进行简单的修改

1
2
3
4
5
6
7
8
def search(path,keyword):
content= os.listdir(path)
for each in content:
each_path = path+os.sep+each
if filename in each:
print(each_path)
if os.path.isdir(each_path):
search(each_path,keyword)

与刚刚不同的只有简单几行

  • 第1行:函数参数增加了要搜索的文件名
  • 第5,6行:增加了判断,我们这里使用‘in’ 而不是‘==’ 的目的是为了使用模糊匹配,只要包含搜索的关键字就符合条件
    -第8行:由于我们整个函数没有修改filename,所以我们可以将搜索条件传递下去

我们这次再来测试,寻找藏起来的target.py

1
>>>search(os.getcwd(),'target')

结果

1
/home/Jkob/Github/test/b/b/target.py

再试一次

1
>>>search(os.getcwd(),'tar')

结果

1
/home/Jkob/Github/test/b/b/target.py

文件内容搜索

然而只有文件名字符合并不能满足我们的需求,我们有时也需要查找文件里面的内容是否符合关键字需求

1
2
3
4
5
6
7
8
def content_search(filepath,keyword):
f = open(filepath,'r')
for line in f:
if keyword in line:
f.close()
return True
f.close()
return False

在这里我们定义了一个函数content_search(),搜索文件内容并默认返回False,如果符合关键字条件即返回True并终端该项搜索

别忘记关闭文件哦

接下来我们将这个函数整合到我们刚刚的文件搜索函数中

关键字搜索整合

我们来把刚才的内容搜索函数添加到我们刚才的搜索函数中

1
2
3
4
5
6
7
8
9
10
def search(path,keyword):
content= os.listdir(path)
for each in content:
each_path = path+os.sep+each
if keyword in each:
print(each_path)
if os.path.isdir(each_path):
search(each_path,keyword)
elif content_search(each_path,keyword):
print(each_path)

我们只添加了最后两行,即当该文件包含关键字时,我们显示该文件路径。但是为什么我们不能把这个和刚才文件名判定条件放在一起呢?因为有的文件名指代的是文件夹,我们需要将其放在文件夹判断之后

我们来测试一下,其实目录下的file.md文件是编辑过的,内容为’target’:

1
search(os.getcwd(),'tar')

返回

#!shell
/home/Jkob/Github/test/b/b/target.py
/home/Jkob/Github/test/a/c/file.md

如果我们将整个文件作为工具的话,我们可以最后一行添加

#!python
search(os.getcwd(),input('Your Keyword:'))

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import os
def search(path,keyword):
content= os.listdir(path)
for each in content:
each_path = path+os.sep+each
if keyword in each:
print(each_path)
if os.path.isdir(each_path):
search(each_path,keyword)
elif content_search(each_path,keyword):
print(each_path)
def content_search(filepath,keyword):
f = open(filepath,'r')
for line in f:
if keyword in line:
f.close()
return True
f.close()
return False
search(os.getcwd(),input('Your Keyword:'))

示例:

1
2
3
4
[Jkob@localhost test] $ python3 test.py 
Your Keyword:tar
/home/Jkob/Github/test/b/b/target.py
/home/Jkob/Github/test/a/c/file.md