文件名1:Data_A_2015-07-29_16-25-55-313.txt
文件名2:Data_B_2015-07-29_16-25-55-313.txt
我需要比较文件夹中的所有Fils,以确保每个TimeStamp都有ONE A和ONE B文件。
Filename的第二个和第二个部分在两个文件中并不总是相同,所以重要的是Date_%H:%M - > 2每分钟的文件是我正在寻找的
(例如:
Data_A_2015-07-29_16-25-55-313.txt
和Data_B_2015-07-29_16-25-54-200.txt
属于一起)
我尝试了以下代码:
for root,dirs,files in os.walk(source):
for a_items in files:
if a_items.__contains__("A"):
A_ALL_List.append(a_items) # One List with all A Files
a_1 = a_item.split('_')[1] # A Part
a_2 = a_item.split('_',)[2] # Date Part
a_3 = a_item.split('_')[3] # TimeStamp %H%M%S%SS incl. .txt
a_4 = a_3.rsplit('.txt',1)[0] # TimeStamp %H%N%S%SS excl. .txt
a_5 = a_4.rsplit ('-',1)[0] # TimeStamp %H%M%S
a_6 = a_5.rsplit ('-',1)[0] # TimeStamp %H%M
a_lvl1 = a_1 + '_' + a_2 +'_' + a_3 # A_Date_FULLTimeStamp.txt
A_Lvl1.append(a_lvl1) # A_Date_TimeStamp.txt LIST
a_lvl2 = a_lvl1.rsplit('.txt',1)[0] # Split .txt
A_Lvl2.append(a_lvl2) # A_Date_TimeStamp LIST
a_lvl3 = a_1 + '_' + a_2 + '_' + a_5 # A_Date_(%H%M%S)TimeStamp
A_Lvl3.append(a_lvl3) # A_Date_(%H%M%S)TimeStamp LIST
a_lvl4 = a_2 + '_' + a_4 # Date_FULLTimeStamp
A_Lvl4.append(a_lvl4) # Date_FULLTimeStamp LIST
a_lvl5 = a_2 + '_' + a_5 # Date_(%H%M%S)TimeStamp
A_Lvl5.append(a_lvl5) # Date_(%H%M%S)TimeStamp LIST
a_lvl6 = a_2 + '_' + a_6 # Date_(%H%M)TimeStamp
A_Lvl6.append(a_lvl6) # Date_(%H%M)TimeStamp LIST
for b_items in files: # Did the same for B now
if b_items.__contains__("B"):
B_All_List.append(b_items)
这样我就获得了两个文件名的列表,这些文件名只包含我要比较的部分 - >例如如果我将列表A_Lvl6与B_Lvl6进行比较,我只会比较日期部分以及时间戳中的小时和分钟。
我发现,B档案比A档案多,所以我继续前进:
for Difference in B_Lvl6: # Data in B
if Difference not in A_Lvl6: # Not in A
DiffList.append(Difference)
这样我得到了数据的输出,其中我没有A文件但是B文件 - > DiffList
现在我想从该DiffList中查找相应的B文件(因为没有匹配的A文件)并将这些B文件移动到另一个文件夹中 - >在主文件夹中应该只有匹配TimeStamps(%H%M)
的A和B文件我的问题(最后):
如何管理最后一部分,我想摆脱没有TimeStamp合作伙伴的所有A或B文件。
我的方法是解决这类问题的正确方法,还是完全疯了?我已经使用Python 1.5周了,所以欢迎任何关于软件包和教程的建议。
我使用的解决方案:
source='/tmp'
import os
import re`
import datetime as dt
pat=re.compile(r'^Data_(A|B)_(\d{4}-\d{2}-\d{2}_\d+-\d+-\d+-\d+)')
def test_list(l):
return (len(l)==2 and {t[1] for t in l}!=set('AB'))
def round_time(dto, round_to=60):
seconds = (dto - dto.min).seconds
rounding = (seconds-round_to/2) // round_to * round_to
return dto + dt.timedelta(0,rounding-seconds,-dto.microsecond)
fnames={}
for fn in os.listdir(source):
p=os.path.join(source, fn)
if os.path.isfile(p):
m=pat.search(fn)
if m:
d=round_time(dt.datetime.strptime(m.group(2), '%Y-%m-%d_%H-%M-%S-%f'), round_to=60)
fnames.setdefault(str(d), []).append((p, m.group(1)))
for k, v in [(k, v) for k, v in fnames.items() if not test_list(v)]:
for fn in v:
print fn[0]
答案 0 :(得分:2)
我认为忽略第二部分和毫秒部分并不是一个好主意。可能会发生一个文件有01:01:59:999而另一个文件有01:02:00:000。差异只有一毫秒,但它也会影响微小部分。更好的解决方案是解析日期时间并计算它们之间的时间差。但是,让我们选择简单的愚蠢版本。我认为这样的事情可以完成这项工作。如果它不是您所需要的,请根据您的需求量身定制:
import os
import re
pattern = re.compile(r'^Data_(?P<filetype>A|B)_(?P<datetime>\d\d\d\d\-\d\d\-\d\d_\d\d\-\d\d)\-\d\d\-\d\d\d\.txt$')
def diff_dir(dir, files):
a_set, b_set = {}, {}
sets = {'A': a_set, 'B': b_set}
for file in files:
path = os.path.join(dir, file)
match = pattern.match(file)
if match:
sets[match.group('filetype')][match.group('datetime')] = path
else:
print("Filename doesn't match our pattern: " + path)
a_datetime_set, b_datetime_set = set(a_set.keys()), set(b_set.keys())
a_only_datetimes = a_datetime_set - b_datetime_set
b_only_datetimes = b_datetime_set - a_datetime_set
for dt in a_only_datetimes:
print(a_set[dt])
for dt in b_only_datetimes:
print(b_set[dt])
def diff_dir_recursively(rootdir):
for dir, subdirs, files in os.walk(rootdir):
diff_dir(dir, files)
if __name__ == '__main__':
# use your root directory here
rootdir = os.path.join(os.path.dirname(__file__), 'dir')
diff_dir_recursively(rootdir)
答案 1 :(得分:1)
我想发布一个部分答案,指出如何将拆分结果分配给名称,并为它们指定有意义的名称。这通常会使解决问题变得容易一些。
def match_files(files):
result = {}
for filename in files:
data, letter, date, time_txt = filename.split('_')
time, ext = time_txt.split('.')
hour, min, sec, ns = time.split('-')
key = date + '_' + hour + '-' + min
# Initialize dictionary if it doesn't already exist.
if not result.has_key(key):
result[key] = {}
result[key][letter] = filename
return result
filename1 = 'Data_A_2015-07-29_16-25-55-313.txt'
filename2 = 'Data_B_2015-07-29_16-25-55-313.txt'
file_list = [filename1, filename2]
match_files(file_list)
输出:
In [135]: match_files(file_list)
Out[135]:
{'2015-07-29_16-25': {'A': 'Data_A_2015-07-29_16-25-55-313.txt',
'B': 'Data_B_2015-07-29_16-25-55-313.txt'}}
答案 2 :(得分:1)
鉴于这五个文件名:
$ ls Data*
Data_A_2015-07-29_16-25-55-313.txt
Data_B_2015-07-29_16-25-54-200.txt
Data_A_2015-07-29_16-26-56-314.txt
Data_B_2015-07-29_16-26-54-201.txt
Data_A_2015-07-29_16-27-54-201.txt
您可以使用正则表达式找到关键信息:Demo
由于我们正在处理时间戳,因此应将时间四舍五入到最接近的时间标记。
这是一个向上或向下舍入到最近的分钟的函数:
import datetime as dt
def round_time(dto, round_to=60):
seconds = (dto - dto.min).seconds
rounding = (seconds+round_to/2) // round_to * round_to
return dto + dt.timedelta(0,rounding-seconds,-dto.microsecond)
将其与循环文件相结合,您可以组合成列表字典,其中键是时间戳四舍五入到一分钟。
(我怀疑你的文件都在同一个目录中,所以我用os.listdir而不是os.walk显示这个,因为os.walk以递归方式遍历多个目录)
import os
import re
import datetime as dt
pat=re.compile(r'^Data_(A|B)_(\d{4}-\d{2}-\d{2}_\d+-\d+-\d+-\d+)')
fnames={}
for fn in os.listdir(source):
p=os.path.join(source, fn)
if os.path.isfile(p):
m=pat.search(fn)
if m:
d=round_time(dt.datetime.strptime(m.group(2), '%Y-%m-%d_%H-%M-%S-%f'), round_to=60)
fnames.setdefault(str(d), []).append((p, m.group(1)))
print fnames
打印:
{'2015-07-29 16:28:00': [('/tmp/Data_A_2015-07-29_16-27-54-201.txt', 'A')], '2015-07-29 16:27:00': [('/tmp/Data_A_2015-07-29_16-26-56-314.txt', 'A'), ('/tmp/Data_B_2015-07-29_16-26-54-201.txt', 'B')], '2015-07-29 16:26:00': [('/tmp/Data_A_2015-07-29_16-25-55-313.txt', 'A'), ('/tmp/Data_B_2015-07-29_16-25-54-200.txt', 'B')]}
这五个文件有一个没有配对的文件。您可以筛选所有非长度为2的文件列表,或者没有A和B对匹配的文件列表。
首先,定义一个测试函数,测试它:
def test_list(l):
return (len(l)==2 and {t[1] for t in l}==set('AB'))
然后使用列表推导来查找不符合条件的dict中的所有条目:
>>> [(k, v) for k, v in fnames.items() if not test_list(v)]
[('2015-07-29 16:28:00', [('/tmp/Data_A_2015-07-29_16-27-54-201.txt', 'A')])]
然后对这些文件采取行动:
for k, v in [(k, v) for k, v in fnames.items() if not test_list(v)]:
for fn in v:
print fn # could be os.remove(fn)
相同的基本方法适用于os.walk
,但您可能在多个目录中有文件。
以下是完整列表:
source='/tmp'
import os
import re
import datetime as dt
pat=re.compile(r'^Data_(A|B)_(\d{4}-\d{2}-\d{2}_\d+-\d+-\d+-\d+)')
def test_list(l):
return (len(l)==2 and {t[1] for t in l}==set('AB'))
def round_time(dto, round_to=60):
seconds = (dto - dto.min).seconds
rounding = (seconds+round_to/2) // round_to * round_to
return dto + dt.timedelta(0,rounding-seconds,-dto.microsecond)
fnames={}
for fn in os.listdir(source):
p=os.path.join(source, fn)
if os.path.isfile(p):
m=pat.search(fn)
if m:
d=round_time(dt.datetime.strptime(m.group(2), '%Y-%m-%d_%H-%M-%S-%f'), round_to=60)
fnames.setdefault(str(d), []).append((p, m.group(1)))
for k, v in [(k, v) for k, v in fnames.items() if not test_list(v)]:
for fn in v:
print fn[0] # This is the file that does NOT have a pair -- delete?