使用通配符在多个文件夹中搜索特定文件(如果存在或不存在)

Searching in multiple folders for specific file if it exists or not using Wildcard

我通过网络搜索并向人们询问了我的“简单”问题,但我没有得到满意的答案。

我的问题如下:

我正在比较来自 Exhange 的数据(以 excel 文件的形式保存在某些文件夹中)和我系统中的数据(SQL 来自数据库的查询)。我正在设计一种工具,用于比较从特定日期到特定日期的数据。我所有的交换数据文件名都基于特定的日期格式,一些字符串和 excel 文件格式各不相同(有时是 .xls、.xlsx、.xlsm)。

显然我需要做的是编写一个循环来搜索从“FROM”日期到“TO”日期所需的文件。假设从 2020 年 7 月 7 日到 2020 年 7 月 13 日。假设 2020 年 7 月 11 日的文件丢失。请记住,我的文件存储在具有 多个子文件夹 的某个位置,这些子文件夹由 MONTH 等命名

示例:

C:\Users\VB\Desktop\VB\python
C:\Users\VB\Desktop\VB\python
C:\Users\VB\Desktop\VB\python

以下是我的文件名的一些示例:

07.07.2020 - BestScore.xls
07.07.2020 - WorstScore.xlsx
08.07.2020 - BestScore.xls
08.07.2020 - WorstScore.xlsx
09.07.2020 - BestScore.xls
09.07.2020 - WorstScore.xls
10.07.2020 - BestScore.xls
10.07.2020 - WorstScore.xlsm
12.07.2020 - BestScore.xls
12.07.2020 - WorstScore.xlsx

我的基本代码如下所示:

import os
from datetime import timedelta

startD = date(2020,7,10)
day= timedelta(days=1)
EndD = date(2020,7,13)

folder = 'C:\Users\VB\Desktop\VB\python'

while startD <= EndD:
    
    date=(startD.strftime("%d.%m.%Y"))
    file = date + '-BestScore'
    file2 = date + '-Worstscore'

    **code IF file or file2 is found ---> do something **
    ** ELSE IF file or file2 is not found ---> print(file or file2 not found)

出现问题是因为我必须使用通配符并且需要搜索多个文件夹(有时我需要比较几个月后的数据, 因此必须在不同的文件夹中搜索)。

我曾尝试使用不同的函数循环访问多个文件夹:

但其中 none 可以按我想要的方式工作。在循环时,这些函数检查每个文件的通配符名称,显然 return 上面的“else if”语句用于未完全命名的每个文件名:

no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713
no file for 20200713

我不需要检查每个文件是否正确,我只想收到这样的结果:

found 07.07.2020 - BestScore.xls
found 07.07.2020 - WorstScore.xlsx
found 08.07.2020 - BestScore.xls
found 08.07.2020 - WorstScore.xlsx
found 09.07.2020 - BestScore.xls
found 09.07.2020 - WorstScore.xls
found 10.07.2020 - BestScore.xls
found 10.07.2020 - WorstScore.xlsm
NOT found 11.07.2020 - Bestscore
NOT found 11.07.2020 - Worstscore
found 12.07.2020 - BestScore.xls
found 12.07.2020 - WorstScore.xlsx

总而言之,我需要一个解决方案来使用 Wildcard* 在多个子文件夹中搜索,而不是使用 IF 语句检查每个文件。

我学习 python 几个月了,我认为这应该不是一个很好解决的问题,但我对此有点困惑。 解决这个问题将完成我的项目,因为其他一切都已经在工作:)

如果有任何帮助,我将非常高兴。

谢谢。

你的问题比较含糊:如果你能提供更多关于文件系统结构的细节就好了..

无论如何,我将您的问题解释如下:给定一个搜索目录和两个日期(开始和结束),您想要在这些日期内搜索两个不同的文件(BestScore 和 WorstScore)。如果它们存在,则执行某些操作,否则,打印警告。

示例:

  • 开始日期:2020 年 7 月 7 日
  • 结束状态:2020 年 7 月 8 日
  • 搜索目录:~/some/dir
  • 允许 file-extensions:xls、xlsm、xlsx

这意味着我们正在寻找四个个文件:

  • ~/some/dir/ ..... /07.07.2020 - BestScore.xls
  • ~/some/dir/ ..... /07.07.2020 - WorstScore.xlsx
  • ~/some/dir/ ..... /08.07.2020 - BestScore.xlsm
  • ~/some/dir/ ..... /08.07.2020 - WorstScore.xlsx

.. 并且它们中的任何一个可能存在也可能不存在于 ~/some/dir 的某个子目录中。我们对其他日期的任何其他文件不感兴趣,无论它们是否存在。

首先,我们需要一些辅助函数。我们从您想对现有文件执行的任何操作开始,此处由 print

表示
def do_something_with(file_path):
  # do something with file ..
  print("doing something with '%s' .." % file_path)

用于确定目录条目是否为文件以及文件类型是否正确的函数,

import os
def is_xls_file(file_path):
  return (os.path.isfile(file_path) and (
    file_path.endswith(".xls") or
    file_path.endswith(".xlsm") or
    file_path.endswith(".xlsx")))

一个函数,用于创建我们正在搜索的文件的字典,

from datetime import date, timedelta
def files_to_find(start_date, end_date, filenames):
  files = {}
  d = start_date
  while d != end_date:
    for fn in filenames:
      files["%s - %s" % (d.strftime("%d.%m.%Y"), fn)] = None
    d += timedelta(days=1)
  return files

然后是实际的搜索功能:我们执行 os.walk(),遍历所有文件和子目录。如果我们找到我们正在寻找的文件,我们将它们的路径存储在 files_to_find 字典中。

def find_files(files_to_find, search_dir):
  for dirpath, subdirs, files in os.walk(search_dir):
    for f in files:
      for ftf in files_to_find:
        # add .lower() for case-insensitivity
        if ftf.lower() in f.lower() and is_xls_file(os.path.join(dirpath,f)):
          files_to_find[ftf] = os.path.join(dirpath,f)
  return files_to_find

我们可以遍历 file_to_find 字典并对存在的文件执行任何需要的操作,并对不存在的文件打印警告,

startD = date(2020,7,10)
EndD = date(2020,7,13)
filenames = ["bestscore", "worstscore"] # the search is case-insensitve
search_dir = "./fold1/fold2"

to_find = files_to_find(startD, EndD, filenames)
found = find_files(to_find, search_dir)

for f,abs_path in found.items():
  if abs_path is None:
    print("Was unable to find '%s'" % f)
  else:
    do_something_with(abs_path)

下面是一个示例 运行 的屏幕截图,其中包含显示的文件系统的结果,使用上面的输入。如前所述,脚本将在这个例子中为每个日期搜索六个个文件(即最佳和最差得分)。因此,它打印正好 六个事件,每个文件一个:它找到了,还是没有..

非常感谢您的详细解释,谢谢。我承认我的问题描述含糊不清。 与此同时,我想出了如何处理我的问题,见下文: 在我的 IT 同事的帮助下,我们找到了一个使用 glob.glob 函数 .

的解决方案
import glob
from datetime import timedelta, date

startD = date(2020,7,10)
day= timedelta(days=1)
EndD = date(2020,7,15)

path = '//some folder'
#print(path)

while startD <= EndD:
    
    date=(startD.strftime("%Y%m%d"))
    file = date + '_best_score*'  # wildcard because of various extension
    file2 = date + '_worst_score*' ## wildcard because of various extension
    result = glob.glob(f'{path}/**/{file}', recursive=True) # search through all subfolders of "path"
    result2 = glob.glob(f'{path}/**/{file2}', recursive=True) # search through all subfolders of "path"
  
    if result or result2:
        print("found file", file)
        print("found file", file2)

    else:
        print("missing", file)
        print("missing", file2)

    startD += day

我认为使用 /**/ 在这里很神奇,因为我有许多子文件夹的名称不同。 此代码仅在找到两个文件时才有效,因此我们修改了 if 语句。作为 glob.glob 函数 returns 两个可能的列表,我们将 result 和 result2 加入 results 列表。

results = result + result2
if len(results) == 2:
        print(results[0]))
        print(results[1]))
elif 1 > len(results) < 2:
    if "best_score" in str(results):
        print("missing", file2)
    else:
        print("missing", file)
else:
    print("missing", file)
    print("missing", file2)

startD += day

你怎么看?

我也会参考你的代码,进一步学习python,再次感谢!