Crossin的编程教室

标题: 【每日一坑 6】 查找文件内容 [打印本页]

作者: crossin先生    时间: 2013-12-26 17:39
标题: 【每日一坑 6】 查找文件内容
Hello 大家好,我终于又来挖坑了。

上次的坑好像反响不是很好,论坛上只有两份解答。其实这题难度不大,不用什么特殊的函数来解决,就是字符串、队列的各种操作,可能会比较烦。如果你要用 python 来处理数据、文件,抓取网页等等,最后也都逃不过各种字符串和队列的操作。

这题本来定的比较宽松,你可以选择按标点划分成新队列,或者按照固定长度划分新队列,然后再按照元素在队列中的位置,重新整合成新队列输出。具体实现就不在微信里发了。

之前说过要挖几个跟文件相关的坑。今天就是在之前“查找文件”的基础上,增加对文件内容的检索。仍然是设定某个文件夹,不同的是要再增加一个文本参数,然后列出这个文件夹(含所有子文件夹)里,所有文件内容包括这个搜索文本的文件。
作者: fl0w    时间: 2013-12-26 22:32
本帖最后由 fl0w 于 2013-12-26 22:35 编辑

findThemAll.py
  1. #! /usr/bin/env python
  2. # coding:utf-8

  3. import sys
  4. import os
  5. import fnmatch
  6. import re

  7. def filterFilename(path, text):
  8.     fileList = []
  9.     for dirpath, dirnames, filenames in os.walk(path):
  10.         for filename in filenames:
  11.             if fnmatch.fnmatch(filename, text):
  12.                 fileList.append(os.path.join(dirpath, filename))
  13.     return fileList

  14. if __name__ == "__main__":
  15.     if len(sys.argv) < 3:
  16.         print 'Please input like this:./findThemAll.py your_dir your_match_string'
  17.     elif os.path.exists(sys.argv[1]):
  18.         fileList = filterFilename(sys.argv[1],'*.txt')
  19.         themAll = []
  20.         for file in fileList:
  21.             with open(file) as f:
  22.                 content = f.read()
  23.                 if len(re.findall(sys.argv[2], content)) > 0:
  24.                     themAll.append(file)
  25.         print 'The files under %s contain "%s" are:' % (sys.argv[1], sys.argv[2])
  26.         print themAll
  27.     else:
  28.         print 'Are you sure the path is exist?'
复制代码

作者: scz_000    时间: 2013-12-27 14:27
这题是不是可以拓展成为比较实用的搜索相关文本功能?不同的格式直接用open是不是默认用记事本打开,里面的那些编码有什么价值啊?小的文件夹还行,尝试的搜整个盘系统就会变得非常慢,用时似乎还要很久。
  1. # coding=gbk
  2. import os,fnmatch
  3. def find_txt(root,patterns='*'):#定义主函数,接受目录与所要匹配的拓展名为参数
  4.     list_of_file=[]#列表储存匹配文件路径
  5.     for dirname,subdir,filenames in os.walk(root):#使用os。walk(遍历包括子目录下所有文件),生成三组列表,第一组为当前目录地址,第二组为当下前目录下的文件夹名(没有则返回一个空列表),第三组为当前目录的所有文件
  6.         for i in filenames:#遍历当前目录下的所有文件,每个文件名加上当前文件夹路径,构成完整的文件路径
  7.             file_object='\\'.join([dirname,i])#构造完整目录
  8.             try:
  9.                 f=open(file_object,'r')#打开文件
  10.                 file_content= f.read()#读取文件
  11.                 if key_words in file_content:#判断关键词是否在文件内容内
  12.                     list_of_file.append(file_object)
  13.             finally:
  14.                 f.close()
  15.     return list_of_file
  16. if __name__=='__main__':
  17.     root=raw_input('所要搜索目录:')
  18.     key_words=raw_input('内容关键词:')
  19.     match_files=find_txt(root)
  20.     if match_files:
  21.         print "以下是包含关键词%s的文件"%key_words
  22.         for i in match_files:
  23.             print i
  24.     else:
  25.         print"没有找到相关文件"
复制代码

作者: crossin先生    时间: 2014-1-2 10:30
scz_000 发表于 2013-12-27 14:27
这题是不是可以拓展成为比较实用的搜索相关文本功能?不同的格式直接用open是不是默认用记事本打开,里面的 ...

open只是在python打开,把内容读入内存,不会调用任何其他程序打开。但这个过程是很慢的。所以虽然可以实现文本搜索,也还是不能用来全盘搜索。
作者: creek    时间: 2014-6-27 00:16
  1. #!/usr/bin/env python
  2. #coding:UTF-8

  3. import os
  4. import re
  5. def VisitDir(path):
  6.   for root,dirs,files in os.walk(path):
  7.       for f in files:
  8.           if os.path.splitext(f)[1]=='.py':
  9.               content=open(os.path.join(root,f),'r').read()
  10.               if re.search('import os',content):
  11.                 print f
  12.          
  13. if __name__=="__main__":
  14.     path="."
  15.     VisitDir(path)
复制代码

作者: manhong2112    时间: 2016-1-16 14:37
  1. import re
  2. import os

  3. def check(dir,text):
  4.   for i in os.listdir(dir):
  5.     if os.path.isdir(i): check(dir + "/" + i,text)
  6.     if re.search(r'.*\.txt',i):
  7.       file = open(dir + "/" + i,encoding="utf8").read()
  8.       print(str(i) + "\n" if re.search(text,file) else "",end="")

  9. check(os.getcwd(),"hello world")
复制代码

作者: xqqxjnt1988    时间: 2016-2-16 15:25
@crossing先生
请帮我看看,新手鼓起勇气努力写了大半天,期待前辈指点,有任何错误,不妥,都请您指出,拜谢
#!\usr\bin\python
#-*-encoding:utf-8-*-
#author=xuqq
#下面这个程序实现的功能是:在一个文件夹,包括子文件夹中,寻找包含相关内容的文件,把这些文件罗列出来
import os,re

def search_in_path(path_original,str_targit):
    targit_files = []
    if (os.path.exists(path_original) and os.path.isabs(path_original)):               
        for root,dir,files in os.walk(path_original):                                    #os.walk()遍历是个好东东
            print root
            print dir
            print files
            
            for file_obj in files:
                file_whole_name = os.path.join(root,file_obj)
                result = search_in_file(file_whole_name,str_targit)
                if result !="":
                    targit_files.append(result)
                else:
                    continue
    else:
        print "The path which you have input is not valid!"
    print "最终包括这个内容的文件有:\n"
    result_num = 0
    for tar in targit_files:
        print "%d\t%s" %(result_num,tar)
        result_num = result_num+1
            
def  search_in_file(file_original,str_targit):
    if os.path.isfile(file_original):
        fp = open(file_original,'r')
        match = False
        line = "file begin:"
        i = 1
        while line:
            line =  fp.readline()
            #print "以下打印内容:\n" ,line
            m = re.findall(str_targit,line)
            #print "m = \t",m
            if m !=[]:
                match =True
                print "在文件里找到了"
                break
            else:
                continue
            i = i+1
        print "%_%"*28
        print "match:\t",match
        if match ==True:
            print "Found it!\t"+file_original
            fp.close()
            print '*'*80
            return file_original
        else:
            print "Nothing found!"
            fp.close()
            print '#'*80
            return ""
            
def main():
    search_in_path("C:\Python27", "xuqq")
   
if __name__ =='__main__':
    main()
作者: crossin先生    时间: 2016-2-16 22:35
xqqxjnt1988 发表于 2016-2-16 15:25
@crossing先生
请帮我看看,新手鼓起勇气努力写了大半天,期待前辈指点,有任何错误,不妥,都请您指出,拜 ...

查找文件里的内容不用readlines,直接read到一个字符串,然后find就可以了。
另外你这个代码好像无法检测子文件夹,因为你没有进一步对dir去递归搜索
作者: morpheus2222    时间: 2017-1-22 09:03
import os
def find_certain_files(keyword = input("search:") ):
    result = []
    for path,dirs,files in os.walk("文件夹"):
        for file in files:
            if file.endswith(".txt"):
                fileWithPath = os.path.join(path,file)
                a = open(fileWithPath)
                b = a.read()
                if keyword in b:
                    result.append(fileWithPath)
                a.close()

    print(result)
find_certain_files()
作者: huiwenwu    时间: 2017-3-7 15:43
模仿上一个题目的一个解答编写的。让用户提供文件夹,文件类型和搜索文本。

#!/usr/bin/python
#This file is used to search files in path A. The names of the files contains B, and the content of the files contain C
#the input should like this:python search.py A B C

import os
import re
import sys

def searchmethod(path,filetype,text):
  all=[]
  for dirpath, dirnames, filenames in os.walk(path):
    for filename in filenames:
      f=file(os.path.join(dirpath,filename))
      content=f.read()
      f.close()
      #print content
      if os.path.splitext(filename)[1]==filetype and re.findall(text, content): # to match file type and file content
        all.append(os.path.join(dirpath,filename))
  print all

if __name__=='__main__':
  if len(sys.argv) !=4:
    print 'Please input like this:./9.py your_dir file_type your_match_string'
  elif os.path.exists(sys.argv[1]):
    searchmethod(sys.argv[1],sys.argv[2],sys.argv[3])

作者: 南斗    时间: 2017-3-27 22:53
  1. #! /usr/bin/env python
  2. #coding=utf-8
  3. import os
  4. rootdir = 'E:\Famine' #定义根目录

  5. #三个参数:分别返回1.父目录 2.父目录下所有文件夹名字(不含路径) 3.父目录下所有文件名字
  6. for father_path, foldernames, filenames in os.walk(rootdir):
  7.    
  8.     for filename in filenames: #遍历文件

  9.         if os.path.splitext(filename)[1] == '.txt': #判断文件后缀是否是txt
  10.             dir = os.path.join(father_path, filename) #组合文件路径
  11.             
  12.             if os.path.exists(dir): #判断文件路径是否存在
  13.                 folder = os.path.split(os.path.split(dir)[0])[1] #获取文件上层文件夹
  14.                 print 'The upper folder is:\n%s' % folder, '\n'
  15.                 print 'The file name is:\n%s' % filename, '\n'
  16.                
  17.                 f = file(dir) #打开文件
  18.                 context = f.read() #读取文件内容
  19.                 print 'The contents of this file is', '\n', context, '\n\n'
  20.                 f.close() #关闭文件
复制代码

作者: xqqxjnt1988    时间: 2017-4-11 15:33
crossin先生 发表于 2016-2-16 22:35
查找文件里的内容不用readlines,直接read到一个字符串,然后find就可以了。
另外你这个代码好像无法检测 ...

谢谢你,crossin先生,我在你的论坛上学习了python之后,就找了一个写python的工作,所以到现在才来看,特意来感谢你的。谢谢!
作者: crossin先生    时间: 2017-4-11 23:29
xqqxjnt1988 发表于 2017-4-11 15:33
谢谢你,crossin先生,我在你的论坛上学习了python之后,就找了一个写python的工作,所以到现在才来看, ...


作者: wolfog    时间: 2017-8-31 11:57

import fnmatch
import os


def filterFile(filePath, contain):
    for grandFather, father, sons in os.walk(filePath):
        sonList = []
        for son in sons:
            sonList.append(son)
        fnmatchs = fnmatch.filter(sonList, "*.txt")
        if len(fnmatchs) != 0:
            for fnmatchFile in fnmatchs:
                absultePath = grandFather + "/" + fnmatchFile
                absultePath = absultePath.replace("\\", "/")
                f = file(absultePath)
                str = f.read()
                f.close()
                if str.__contains__(contain):
                    print absultePath


path = raw_input("请输入遍历的绝对路径:")
filterFile(path, "aaa")

做的过程中存在两个问题困扰了我:
1、sonList刚开始在方法外放着,导致生命周期太长,所以导致了我的拼接出来的路径下不存在某个文件
2、拼接出来的路径是双引号的,用来打开文件会出错。但是我敲的demo在pycharm中打印出来却是单斜杠的。一直不知道是哪里出问题了。最后发现是pycharm自动将其转化为合格的路劲。
作者: coolqing    时间: 2018-5-16 16:48
我这边自己建了一个文件夹,里面放了一个子文件夹,一些txt、excel和word文件。
运行代码后,txt文件正常显示内容,excel和word都不正常。
自己搜索了下,说是excel和word的读取要用其他模块来处理的,但是基础课程中讲到read的使用时,老师好像也没有提到txt文件之外的类型该怎么读取,麻烦问下老师excel这些是要再另外处理吗?

1526460289(1).jpg (17.28 KB, 下载次数: 446)

1526460289(1).jpg

1526460267(1).jpg (9.67 KB, 下载次数: 424)

1526460267(1).jpg


作者: crossin先生    时间: 2018-5-17 22:42
coolqing 发表于 2018-5-16 16:48
我这边自己建了一个文件夹,里面放了一个子文件夹,一些txt、excel和word文件。
运行代码后,txt文件正常显 ...

excel、word是不能直接读取的,要读写的话,需要用专门的库
公众号回复 excel 有介绍
作者: highhig    时间: 2018-8-23 11:46
crossin先生 发表于 2014-1-2 10:30
open只是在python打开,把内容读入内存,不会调用任何其他程序打开。但这个过程是很慢的。所以虽然可以实 ...

import os
import re
dirnme = 'E:\Study during Graduate school'
list_dir = []
for dirnow,folds,files in os.walk(dirnme):
    # print(dirnow)
    # print(folds)
    # print(files)
    for fs in files:
        # print(fs)
        filtext = re.findall('.txt',fs)
        if filtext:
            list_dir.append(os.path.join(dirnow, fs))
    # filtext = re.findall("*.txt",files)
    # list_dir.append(''.join(dirnow,files))
print(list_dir)
作者: jodie    时间: 2020-10-14 23:22
  1. import os
  2. import chardet

  3. def match(search_path,match_text):
  4.     result_list = []

  5.     for root, dirs, files in os.walk(search_path):
  6.         # 遍历所有的文件
  7.         for file in files:
  8.             # 判断文件名是否以“.txt”结尾
  9.             if file.endswith(".txt"):

  10.                 # 获取文件的绝对路径
  11.                 file_path = os.path.join(root,file)
  12.                 # print(file_path)

  13.                 # 判断文件的编码格式
  14.                 with open(file_path, "rb") as obj1:
  15.                     text_b = obj1.read()
  16.                     text_encoding = chardet.detect(text_b)["encoding"]
  17.                     # print(text_encoding)

  18.                 # 用指定的编码格式打开文件,判断文本参数是否存在于文件内容
  19.                 with open(file_path, "r", encoding=text_encoding) as obj2:
  20.                     text = obj2.read()
  21.                     if match_text in text:
  22.                         result_list.append(file_path)

  23.     return result_list


  24. if __name__ == "__main__":

  25.     # 提示用户输入路径
  26.     while True:
  27.         search_path = input("请输入搜索路径: ").strip()
  28.         # 判断路径是否存在
  29.         if os.path.exists(search_path):
  30.             break
  31.         print("路径不存在!")
  32.     # 提示用户输入匹配的文字
  33.     match_text = input("请输入匹配的文字: ")
  34.     file_list = match(search_path,match_text)
  35.     # 展示匹配到的文件
  36.     print("匹配到的文件如下: ")
  37.     for one in file_list:
  38.         print(one)
复制代码

result.png (7.75 KB, 下载次数: 397)

result.png


作者: crossin先生    时间: 2020-10-15 13:02
jodie 发表于 2020-10-14 23:22

实际运用中,因为文件夹下可能有很多非文本文件,所以最好加上异常处理,避免报错跳出
作者: FERRYMAN    时间: 2021-2-13 19:24
老师好,能看看嘛?望得到您的建议。

这个程序有些问题。比如我在文件夹中加上一个Word文件,它就会报错。大概是这样:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 89: illegal multibyte sequence
老师能解释一下和提供个解决方法吗?谢谢啦!
  1. import os

  2. text = input('输入要检索的内容:\n')
  3. way = input('输入要检索的文件夹位置:\n')
  4. result = []

  5. for root, dirs, files in os.walk(way):
  6.     for f in files:
  7.         file_con = open(root + '\\' + f,encoding = 'utf-8').read()
  8.         if text in file_con:
  9.             result.append(f)
  10. print(result)
复制代码

作者: crossin先生    时间: 2021-2-13 20:14
FERRYMAN 发表于 2021-2-13 19:24
老师好,能看看嘛?望得到您的建议。

这个程序有些问题。比如我在文件夹中加上一个Word文件,它就会报错。 ...

word无法直接当做文本读写,可以通过异常处理来跳过。或者要用 python-docx库打开
作者: FERRYMAN    时间: 2021-2-13 21:05
crossin先生 发表于 2021-2-13 20:14
word无法直接当做文本读写,可以通过异常处理来跳过。或者要用 python-docx库打开 ...

老师,我还有些问题。

报错UnicodeDecodeError的原因就是文件夹里的Word无法直接读是吗?
如果是,那如果文件夹里还有Excel,PPT之类,也要把那些库一个一个下载来用是吗?应该怎么办?
作者: crossin先生    时间: 2021-2-16 22:33
FERRYMAN 发表于 2021-2-13 21:05
老师,我还有些问题。

报错UnicodeDecodeError的原因就是文件夹里的Word无法直接读是吗?

看你具体什么需求,如果是需要检索的话,那确实是要的

作为这个练习来说,能做到检索txt内容和其他文件的名字就够了
作者: FERRYMAN    时间: 2021-2-17 11:05
crossin先生 发表于 2021-2-16 22:33
看你具体什么需求,如果是需要检索的话,那确实是要的

作为这个练习来说,能做到检索txt内容和其他文件 ...

好的,谢谢老师




欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5