Python使用正则表达式在子文件夹中搜索文件名并附加到列表以供进一步使用

时间:2012-04-05 07:48:25

标签: regex list search python-2.6 subdirectory

我的文件系统包含大量文件夹,文件夹名称格式为4位数。在每个文件夹中有不同格式的不同数量的文件,名称对应于文件夹名称,一些文件附加了字母和/或日期。我想做的是搜索每个文件夹,如果一年的格式为“19 ??”或“20 ??”找到后,创建一个标有该年份的文件夹。如果文件名还包含表达式“ED *”,请创建一个带有该标签的子文件夹。创建所有文件夹后,将所有文件复制到相应的文件夹中,并将名称删除到前6个字符。此文件结构将在单独的驱动器上创建。

示例:文件夹MAIN包含许多子文件夹,例如2742,2830,3417等。文件夹2742包含文件

  • 2742AB.txt
  • 2742AB_1999.tif
  • 2742BB_1999_ED1.txt
  • 2742AC_1999_ED2_FINAL.txt
  • 2742CC_2001_ED4.tif

运行脚本后,文件夹结构应如下所示:

  • MAIN \ 2742 \ 2742AB.txt
  • MAIN \ 2742 \ 1999 \ 2742AB.tif
  • MAIN \ 2742 \ 1999 \ ED1 \ 2742BB.txt
  • MAIN \ 2742 \ 1999 \ ED2 \ 2742AC.txt
  • MAIN \ 2742 \ 2001 \ ED4 \ 2742CC.tif

在这里搜索类似示例后使用各种代码片段,我提出了以下内容:     进口口     folder ='C:\ MAIN'     os.chdir(文件夹)

dirlist = []
for dirname, dirnames, filenames in os.walk(folder):
    for subdirname in dirnames:
        dirlist.append(subdirname)
    for filename in filenames:
        dirlist.append(filename)

我的问题是下一部分,即修改上述搜索以首先检查该值是否已在列表中。如果它在列表中,继续搜索,否则检查文件名是否包含正则表达式,如果是,则将其添加到数组中。在(某种)psuedocode:

initialise list years
#search through folders etc
for filenames in folders
    if filename contains either regex
        for values in years
            if filename exists
                skip it and continue searching
            else
                append filename to years

我已经看过这里有关使用正则表达式等搜索文件夹的各种答案,但我不完全确定我使用的方法是否正确。对我所使用的方法的任何建议和/或评论都将不胜感激。

修改我编辑的代码,使用下面的Michal建议并自行修改一下:

import os, re, shutil
tfolder = 'C:\\MAIN'
os.chdir(tfolder)

re_year19xx = re.compile('(19[0-9][0-9])')
re_year20xx = re.compile('(20[0-9][0-9])')
re_ed = re.compile('(ed[0-9]\d+)', re.IGNORECASE)
destPath = 'C:\\DEST'

filePath, coords = os.path.split(fname)
coordsFolder = coords[:4]
coordsFname = coords[:6]
coordsExt = os.path.splitext(fname)
year = ' ' #create variable year
ed = ' ' #create variable ed to store the edition number if necessary
bname = fname #the original file name
for re_year in (re_year19xx, re_year20xx):
    rx = re_year.search(fname) #search for regex in the file name and store it in rx
    if rx:
        year = rx.group(1) #if the regex is found, store the year
        print(year)
        bname.replace(year, ' ')
        re_searchEd = re_ed.search(fname)
        if re_searchEd:
            ed = re_searchEd.group(1)
            bname.replace(ed, ' ')
    os.chdir(destPath)  
    fname2 = os.path.join(destPath, coordsFolder,year, ed) + coordsFname + coordsExt[1]
    print('%s -> %s' % (fname, fname2))
    dirn, _ = os.path.split(fname2)
    if not os.path.exists(dirn):
        os.makedirs(dirn)
    shutil.copy(fname, fname2)

for root, dirs, files in os.walk(tfolder):
    for name in files:
        fn = os.path.join(root, name)
        analyse_file_name(fn)

再次查看我的代码,一切似乎都正常工作,直到它必须创建子文件夹,即创建coordsFolder后,如果year不为空,则创建子文件夹,如果{{1不是空白,创建子文件夹,然后将原始文件复制到相应的子文件夹并重命名。文件夹ed的调试print语句的结果如下:

2742

修改添加C:\MAIN\2742\2742AB.txt -> C:\DEST\2742\year\ed2742AB.txt C:\MAIN\2742\2742AB.txt -> C:\DEST\2742\year\ed2742AB.txt 1999 C:\MAIN\2742\2742AB_1999.tif -> C:\DEST\2742\1999\ed2742AB.tif C:\MAIN\2742\2742AB_1999.tif -> C:\DEST\2742\1999\ed2742AB.tif 1999 C:\MAIN\2742\2742AC_1999_ED2_final.tif -> C:\DEST\2742\1999\ed2742AC.tif C:\MAIN\2742\2742AC_1999_ED2_final.tif -> C:\DEST\2742\1999\ed2742AC.tif 1999 C:\MAIN\2742\2742BB_1999_ED1.txt -> C:\DEST\2742\1999\ed2742BB.txt C:\MAIN\2742\2742BB_1999_ED1.txt -> C:\DEST\2742\1999\ed2742BB.txt C:\MAIN\2742\2742CC_2001_ED4.tif -> C:\DEST\2742\year\ed2742CC.tif 2001 C:\MAIN\2742\2742CC_2001_ED4.tif -> C:\DEST\2742\2001\ed2742CC.tif 1999 的值后检查:

year

正确创建npw路径,并将文件复制到正确的位置并正确重命名!所以问题的最后部分现在适用于if year is 'year': fname2 = os.path.join(destPath, coordsFolder) + '\\' + coordsFname + coordsExt[1] else: fname2 = os.path.join(destPath, coordsFolder,year) + '\\' + coordsFname + coordsExt[1] 子文件夹。目前,代码只是忽略了文件名中包含“ED1”,“ED2”等的部分。如果ed的值不是“ed”的初始值>

,我在哪里放置代码来创建子文件夹

2 个答案:

答案 0 :(得分:0)

你应该创建分析文件名的函数 - 拆分它的部分,用你想要的东西替换它们等。这样的函数的例子:

re_year19xx = re.compile('(19\d\d)')
re_year20xx = re.compile('(20\d\d)')

re_ed = re.compile('(ed\d+)', re.IGNORECASE)


def analyze_file_name(fname):
    digits = fname[:4]
    year = ''
    ed = ''
    bname = fname
    for re_year in (re_year19xx, re_year20xx):
        rx = re_year.search(fname)
        if rx:
            year = rx.group(1)
            bname = bname.replace(year, '')
    rx = re_ed.search(fname)
    if rx:
        ed = rx.group(1)
        bname = bname.replace(ed, '')
    fname2 = os.path.join('MAIN', digits, year, ed, bname)
    fname2 = fname2.replace('_', '')
    print('%s -> %s' % (fname, fname2))

如果要将文件移动(重命名)到新目的地,则可以检查&创建目标目录,然后在那里移动文件。代码可能如下所示:

    ...
    fname2 = fname2.replace('_', '')
    dirn, _ = os.path.split(fname2)
    if not os.path.exists(dirn):
        os.makedirs(dirn)
    os.rename(fname, fname2)
    print('%s -> %s' % (fname, fname2))

如果您想同时拥有源文件和目标文件,则可以使用os.rename()代替shutil.copy()

您对os.walk()也有疑问。在当前形式中,您将多次获得相同的文件名,analyze_file_name()将仅获取文件名的最后一部分(即没有目录)。我将向您展示如何获得完整的文件名:

for root, dirs, files in os.walk(tfolder):
    for name in files:
        fn = os.path.join(root, name)
        analyse_file_name(fn)

您还可以将带有目录名称的额外参数添加到analyse_file_name()

基于您创建目录的最后一个源的完整版:

def analyse_file_name(fname):
    filePath, coords = os.path.split(fname)
    coordsFolder = coords[:4]
    coordsFname = coords[:6]
    coordsExt = os.path.splitext(fname)
    year = 'year' #create variable year
    ed = 'ed' #create variable ed to store the edition number if necessary
    bname = fname #the original file name
    for re_year in (re_year19xx, re_year20xx):
        rx = re_year.search(fname) #search for regex in the file name and store it in rx
        if rx:
            year = rx.group(1) #if the regex is found, store the year
            print(year)
            bname.replace(year, ' ')
            re_searchEd = re_ed.search(fname)
            if re_searchEd:
                ed = re_searchEd.group(1)
                bname.replace(ed, ' ')
        fname2 = os.path.join(destPath, coordsFolder,year, ed)
        fname2 = fname2 + coordsFname + coordsExt[1]
        print('%s -> %s' % (fname, fname2))
        dirn, _ = os.path.split(fname2)
        if not os.path.exists(dirn):
            os.makedirs(dirn)
        shutil.copy(fname, fname2)

答案 1 :(得分:0)

我的问题的最终答案(经过大量编辑和@Michal Niklas的大量帮助后:

import os, re, shutil

tfolder = 'C:\\MAIN'

os.chdir(tfolder)

re_year19xx = re.compile('(19[0-9][0-9])')
re_year20xx = re.compile('(20[0-9][0-9])')

re_ed = re.compile('(ED[0-9])')
destPath = 'C:\\DEST'

def analyse_file_name(fname):
    filePath, coords = os.path.split(fname) #the new folders will be named according to the first 4 characters of the original file name
    coordsFolder = coords[:4]
    coordsFname = coords[:6]
    coordsExt = os.path.splitext(fname)
    year = 'year' #create variable year
    ed = 'ed' #create variable ed to store the edition number if necessary
    bname = fname #the original file name
        for re_year in (re_year19xx, re_year20xx):
        rx = re_year.search(fname) #search for regex in the file name and store it in rx
        if rx:
            year = rx.group(1) #if the regex is found, store the year
            bname.replace(year, ' ')
            res = re_ed.search(fname)
            if res:
                ed = res.group(1)
                bname.replace(ed, ' ')
        os.chdir(destPath)  
        if year is 'year':
            fname2 = os.path.join(destPath, coordsFolder) + '\\' + coordsFname + coordsExt[1]
        else:
            fname2 = os.path.join(destPath, coordsFolder,year,ed) + '\\' + coordsFname + coordsExt[1]
        print('%s -> %s' % (fname, fname2)) #debug print
        dirn, _ = os.path.split(fname2)
        if not os.path.exists(dirn):
            os.makedirs(dirn)
        shutil.copy(fname, fname2)

for root, dirs, files in os.walk(tfolder):
    for name in files:
        fn = os.path.join(root, name)
        analyse_file_name(fn)