题目
编写一个程序:
1、能在当前目录以及当前目录的所有子目录下查找文件名包含指定字符串的文件;
2、并打印出相对路径。
思路
1. 这道题目是要用到递归的,递归中return的陷阱,请参考上篇博文《python递归中的return"陷阱"》
2. 涉及到正则的部分考虑用re.serach方法
3. 可以先匹配到目录或文件,返回文件名/目录名,后续再优化
4. 优化:过滤目录的匹配,打印相对路径,如果不设置匹配字符串,则返回当前目录下的所有文件
初步方案一:
这个方案有个很大的问题是return func(new_dir)只会递归第一个目录excel操作下的所有目录,当excel目录递归到最底层,dir_list变成['my_excel.py', 'testdata.xlsx']后,if 和 elif 条件都不满足,此时的func(new_dir)层层返回给最外层func()的结果是None,有了返回值,意味着这个函数的结束,那么for item in dir_list:后面没有得到执行
import os, re def func(base_dir): dir_list = os.listdir(base_dir) print(dir_list) for item in dir_list: new_dir = os.path.join(base_dir, item) if re.search("Common", item): return item elif os.path.isdir(new_dir): print(new_dir) return func(new_dir) print(func(os.getcwd()))
运行结果:
['demo.py', 'demo4.py', 'demo_2.py', 'demo_3.py', 'excel操作', 'future_loan', 'hello.txt', 'poem.txt', 'python_API_framework', 'try_except.py', '函数.py', '列表.py', '基本语法和常用运算符.py', '字典.py', '字符串.py', '文件操作.py', '日志', '私有属性和方法.py', '类和对象(一).py', '类和对象(二).py', '类和对象作业(二).py', '练习(一)login.py', '练习(二)查找文件.py', '装饰器.py'] D:python_workshoppython6 eviseexcel操作 ['my_excel.py', 'testdata.xlsx'] None
初步方案二:
鉴于这一点,必须摒弃方案一中的return,即使在上一篇文章《python递归中的return"陷阱"》中看到,global和return(func(i))的方法都奏效,但注意这道题是有for循环的,所以采用global的方法
import os, re result = None def func(base_dir): dir_list = os.listdir(base_dir) print(dir_list) for item in dir_list: new_dir = os.path.join(base_dir, item) if re.search("Common", item): global result result = item elif os.path.isdir(new_dir): func(new_dir) return result print(func(os.getcwd()))
运行结果正常:
['demo.py', 'demo4.py', 'demo_2.py', 'demo_3.py', 'excel操作', 'future_loan', 'hello.txt', 'poem.txt', 'python_API_framework', 'try_except.py', '函数.py', '列表.py', '基本语法和常用运算符.py', '字典.py', '字符串.py', '文件操作.py', '日志', '私有属性和方法.py', '类和对象(一).py', '类和对象(二).py', '类和对象作业(二).py', '练习(一)login.py', '练习(二)查找文件.py', '装饰器.py'] ['my_excel.py', 'testdata.xlsx'] ['driver', 'run_all_test.py', 'test_related', '__init__.py'] ['__init__.py'] ['test_case', 'test_data', 'test_report', '__init__.py'] ['login_case.py', 'model', 'page_object', '__init__.py'] ['driver.py', 'function.py', 'myunit.py', '__init__.py'] ['base.py', 'home_page.py', 'login_page.py', '__init__.py'] ['__init__.py'] ['image', '__init__.py'] ['__init__.py'] ['Common', 'HTMLTestReport', 'Logs', 'main.py', 'TestCases', 'TestDatas', '__init__.py', '__pycache__'] ['xiaozhai_API_testReport2018-06-24_19-22-03.html', 'xiaozhai_API_testReport2018-06-24_19-41-26.html', '__init__.py'] ['Autotest_log_2018-06-24 1922.log', 'Autotest_log_2018-06-24 1926.log', 'Autotest_log_2018-06-24 1929.log', 'Autotest_log_2018-06-24 1941.log', '__init__.py'] ['test_api.py', '__init__.py', '__pycache__'] ['test_api.cpython-34.pyc'] ['api_info.xlsx', '__init__.py'] ['__init__.cpython-34.pyc'] ['autotest.log', 'demo.py', '日志_1.py'] Common
优化后的代码
import os, re result = None
result_list = []
#优化1:搜索字符串参数化 def func(base_dir, search_str=None): dir_list = os.listdir(base_dir) #优化2:如果搜索字符串为空,则返回当前目录下的所有文件和目录 if search_str == None: return dir_list for item in dir_list: new_dir = os.path.join(base_dir, item) #优化3:过滤目录的匹配 if os.path.isfile(new_dir): if re.search(search_str, item): global result #优化4:返回相对路径 #os.curdir表示以相对路径的形式表示当前目录. #new_dir表示找到的文件的绝对路径,以当前目录的路径做分割,取出第二个元素,拼接起来 result = os.curdir + new_dir.split(os.getcwd())[1]
result_list.append(result) else: func(new_dir, search_str) return result_list print(func(os.getcwd(), "python"))
运行结果
['.\999python999s.py', '.\test\2python3.py', '.\test\__python__.txt', '.\test2\6python.py', '.\test2\test3\test.python.yml']