微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

比较两个文件名列表+大小+修改时间

如何解决比较两个文件名列表+大小+修改时间

对于一个学生项目,我构建了一个脚本来仅将“新”文件复制到远程库。 我能够找到远程文件夹中不存在的文件并复制它,它正在工作。 现在,我尝试复制具有相同名称但具有不同大小或修改日期的文件

我能够创建一个包含所有所需信息的本地文件列表:

localfilestime = os.scandir(_SOURCE)

print("fichiers sur répertoire source: \n ")

for file in localfilestime:

    localfilestime = (file.stat().st_size,file.stat().st_mtime,file.name)
    print (localfilestime)

远方的也一样:

ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy() )
ssh.connect(_RMTHOST,username=_USR,password=_DESTPASS)

ftp = ssh.open_sftp()
distfilestime = ftp.listdir_attr(_DEST)

print("fichiers sur répertoire de destination: \n")
for f in distfilestime:
    distfilestime =(f.st_size,f.st_mtime,f.filename)
    print (distfilestime)

我得到两个排序列表,但我有两个问题:

fichiers sur répertoire source: 
 
(915,1622736305.82416,'20_060_12C_24T_3800_AMD_Ryzen_9_3900X_12_Core_Processor_64_Bit.txt')
(9602,1624743218.308332,'blabla.txt')
(143897,1583941480.0,'Projet4_configuration_navigateur_proxy01.jpg')
(0,1624520128.9788647,'testcopie.txt')
**********************************************************************************************************

fichiers sur répertoire de destination: 

(915,1622736305,'20_060_12C_24T_3800_AMD_Ryzen_9_3900X_12_Core_Processor_64_Bit.txt')
(37,1624738406,1583941480,1624520128,'testcopie.txt')
  1. 本地列表中的 mtime 返回一个浮点数,而不是远处的,我认为无法正确比较这些数字。

  2. 我找不到一个可行的解决方案来比较这些文件列表,我尝试了很多解决方案,但“不那么糟糕”:

    def get_difference(list_a,list_b):
        return set(list_a) - set(list_b)
    
    
    list_a = localfilestime
    list_b = distfilestime
    
    non_match = list(get_difference(list_a,list_b))
    print("No match elements: ",set(non_match))
    

    只返回一个修改文件 mtime,而不是像 "blabla.txt" 这样不同大小的文件

    No match elements:  {1624520128.9788647}
    

我确定我在某个地方犯了错误,也许我的方法不好。有人可以帮我解答这个问题吗?

编辑:这是整个脚本,在 2 个局域网服务器之间的 Win10 上使用 (1 个物理,1 个在私有共享网络上的 VirtualBox)脚本调用配置文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import socket
import paramiko
import pysftp
import shutil




# importation des variables globales
from configuration import _USR,_RMTHOST,_DESTPASS,_PORT,_SOURCE,_DEST,_EXCLUSION,_TIMEDATE,_OUTPUT

#DéFinition de la variable globale nécessaire à la création du dussier temporaire de copie
_SOURCE_TEMP = (_SOURCE + "temp")

#effacer dossier temporaire en cas d'erreur du script précédent
if os.path.exists(_SOURCE_TEMP):
    shutil.rmtree(_SOURCE_TEMP)


# énoncé du script

print("\ncopie miroir du dossier: " + _SOURCE + "  vers:" + _RMTHOST +(": ") + _DEST)

print("\n**********************************************************************************************************\n")

# vérifier présence du fichier de configuration
try:
    with open('configuration.py'):
        pass
        print("le fichier de configuration est présent et valide")
except IOError:
    sys.exit("Erreur: le fichier de configuration n’est pas present,annulation du backup")

print("\n**********************************************************************************************************\n")


# Vérifier l'accès au fichier source

if os.path.exists(_SOURCE):
    print("le dossier source: ","est valide et accessible \n \n")
else:
    print("le dossier source: ","n\’est pas valide/existant,annulation du backup \n \n")
    sys.exit()

print("**********************************************************************************************************\n")
# test de connexion vers le serveur distant

with socket.socket(socket.AF_INET,socket.soCK_STREAM) as s:
    try:
        s.connect((_RMTHOST,_PORT))
        s.sendall(b'Hello,world')
        data = s.recv(1024)
        print('communication réussie avec le serveur ' + _RMTHOST,repr(data) + ('\n \n'))

    except Exception as ex:
        print(
            "impossible de se connecter au serveur,vérifiez vos identifiants\n \n************************ \n\nannulation de la sauvegarde")
        sys.exit()

print("**********************************************************************************************************\n")

# création de liste de fichiers locaux

localfilestime = os.scandir(_SOURCE)


print("fichiers sur répertoire source: \n ")

for f in localfilestime:

    localfilestime = (f.stat().st_size,f.stat().st_mtime,f.name)

    print (localfilestime)



print("**********************************************************************************************************\n")

#connexion pour listing fichiers présents répertoire distant
ssh = paramiko.SSHClient()

# importation auto de clé de connexion avec le client
ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy())
ssh.connect(_RMTHOST,password=_DESTPASS)

ftp = ssh.open_sftp()

distfilestime = ftp.listdir_attr(_DEST)

print("fichiers sur répertoire de destination: \n")
for f in distfilestime:
    distfilestime =(f.st_size,f.filename)
    print (distfilestime)


#comparaison éléments

loc_files = {}
for f in localfilestime:
    size = f.stat().st_size
    time = int(f.stat().st_mtime)
    name = f.name
    loc_files[(size,time,name)] = f

srv_files = {}
for f in distfilestime:
    size = f.st_size
    time = f.st_mtime
    name = f.filename
    srv_files[(size,name)] = f


# get lists of unique files based on keys (size,name) of these dicts

loc_uniq = [ loc_files[x] for x in loc_files if x not in srv_files ]
srv_uniq = [ srv_files[x] for x in srv_files if x not in loc_files ]

print(loc_uniq)

print("\n**********************************************************************************************************\n")

# création du répertoire temporaire pour copie
_SOURCE_TEMP = (_SOURCE + "temp")

if not os.path.exists(_SOURCE_TEMP):
    os.makedirs(_SOURCE_TEMP,exist_ok=True)

#clôture de la connexion avec le serveur distant
ssh.close()
ftp.close()

#copie des fichiers absents du répertoire distant sur le dossier temporaire pour transfert

os.chdir(_SOURCE)

for files in loc_uniq:
    shutil.copy2(files,_SOURCE_TEMP)

#retirer fichiers à exclure
os.chdir(_SOURCE_TEMP)
files = [f for f in os.listdir('.') if os.path.isfile(f)]

for f in files:
    if f.endswith(_EXCLUSION):
        print(f,"ne sera pas copié selon la liste d'exclusion")
        os.remove(f)

os.chdir(_SOURCE)

print("\n**********************************************************************************************************\n")

#copie des fichiers dans le répertoire distant

with pysftp.Connection(host=_RMTHOST,password=_DESTPASS) as sftp:
    sftp.put(_SOURCE_TEMP,preserve_mtime=True)

    sftp.close()

if os.path.exists(_SOURCE_TEMP):
    shutil.rmtree(_SOURCE_TEMP)

配置文件

import time

_EXCLUSION = '.ini'
_SOURCE = "C:\\Users\\XXX\\testp6\\"
_OUTPUT = _SOURCE + time.strftime('%Y_%m_%d-%Hh%Mmin%ss')
_TIMEDATE = time.strftime('%Y_%m_%d-%Hh%Mmin%ss')
_DEST = "C:\\Users\\XXXx\\test_distant_p6\\"
_USR = 'XXX'
_RMTHOST ='192.168.56.103'
_DESTPASS='XXX'
_PORT=22

和实际回报:

copie miroir du dossier: C:\Users\Jerem\testp6\  vers:192.168.56.103: C:\Users\turmix\test_distant_p6\

**********************************************************************************************************

le fichier de configuration est présent et valide

**********************************************************************************************************

le dossier source:  C:\Users\Jerem\testp6\ est valide et accessible 
 

**********************************************************************************************************

communication réussie avec le serveur 192.168.56.103 b'SSH-2.0-OpenSSH_for_Windows_8.1\r\n'
 

**********************************************************************************************************

fichiers sur répertoire source: 
 
(915,'blabla.txt')
(46,1624736892.7385924,'desktop.ini')
(143897,'Projet4_Jeremie_Voita_configuration_navigateur_proxy01.jpg')
(0,'testcopie.txt')
Traceback (most recent call last):
  File "C:\Users\jerem\OneDrive\P6\pythonP6\dernierendate.py",line 118,in <module>
    size = f.stat().st_size
AttributeError: 'int' object has no attribute 'stat'

Process finished with exit code 1

解决方法

它可以通过多种方式完成。例如这种方式:

localfilestime = [
    (915,1622736305.82416,'20_060_12C_24T_3800_AMD_Ryzen_9_3900X_12_Core_Processor_64_Bit.txt'),(9602,1624743218.308332,'blabla.txt'),(143897,1583941480.0,'Projet4_configuration_navigateur_proxy01.jpg'),(0,1624520128.9788647,'testcopie.txt'),]

distfilestime = [
    (915,1622736305,(37,1624738406,1583941480,1624520128,]

# convert float dates into integer dates
localfilestime = [(size,int(date),name) for (size,date,name) in localfilestime]

# convert every element of the lists into a { key:value }
localfilestime = { str(x):x for x in localfilestime }
distfilestime  = { str(x):x for x in distfilestime  }

# get unique values from the lists
localfilestime_uniques = { localfilestime[x] for x in localfilestime if x not in distfilestime  }
distfilestime_uniques  = { distfilestime[x]  for x in distfilestime  if x not in localfilestime }

print(localfilestime_uniques) # {(9602,1624743218,'blabla.txt')}
print(distfilestime_uniques)  # {(37,'blabla.txt')}

更新

可能你需要这个:

# make the dicts { (size,time,name) : file }

loc_files = {}
for f in localfilestime:
    size = f.stat().st_size
    time = int(f.stat().st_mtime)
    name = f.name
    loc_files[(size,name)] = f

srv_files = {}
for f in distfilestime:
    size = f.st_size
    time = f.st_mtime
    name = f.filename
    srv_files[(size,name)] = f


# get lists of unique files based on keys (size,name) of these dicts

loc_uniq = [ loc_files[x] for x in loc_files if x not in srv_files ]
srv_uniq = [ srv_files[x] for x in srv_files if x not in loc_files ]

理论上它应该可以工作,它应该为您提供两个具有唯一文件的列表(基于大小、时间、名称)。但是我无法正确测试它,因为我没有包含您文件的 FTP 服务器。


我已经在 Windows 和 Mac 上测试了代码的本地部分,这部分工作得很好:

import os
from pprint import pprint

localfilestime = os.scandir(r"c:\\temp")

loc_files = {}
for f in localfilestime:
    size = f.stat().st_size
    time = int(f.stat().st_mtime)
    name = f.name
    loc_files[(size,name)] = f

pprint(loc_files)

输出示例:

{(0,1622330493,'test - Copy.txt'): <DirEntry 'test - Copy.txt'>,'test.txt'): <DirEntry 'test.txt'>,(124,1622332489,'test.zip'): <DirEntry 'test.zip'>,(267,1624901883,'loc_files.py'): <DirEntry 'loc_files.py'>}
,

感谢@Yuri Khristich,我有一个完美的解决方案:

使用:

import os
import sys
import socket
import paramiko
import pysftp
import shutil
from pprint import pprint

#for local files

localfilestime = os.scandir(r"c:\\temp")

loc_files = {}
for f in localfilestime:
    size = f.stat().st_size
    time = int(f.stat().st_mtime)
    name = f.name
    loc_files[(size,name)] = f

print("fichiers sur répertoire source: \n ")
pprint(loc_files)

#for distant files

ssh = paramiko.SSHClient()

# importation auto de clé de connexion avec le client
ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy())
ssh.connect(_RMTHOST,username=_USR,password=_DESTPASS)

ftp = ssh.open_sftp()

distfilestime = ftp.listdir_attr(_DEST)

dst_files = {}
for f in distfilestime:
    size = f.st_size
    time = f.st_mtime
    name = f.filename
    dst_files[(size,name)] = f

print("fichiers sur répertoire de destination: \n")
pprint(dst_files)

#clôture de la connexion avec le serveur distant
ssh.close()
ftp.close()

#create a list of files not present/differents(name,size,modification date) on the distant server:

loc_uniq = [ loc_files[x] for x in loc_files if x not in dst_files ]

#create a temp folder to copy the different files

_SOURCE_TEMP = (_SOURCE + "temp")

if not os.path.exists(_SOURCE_TEMP):
    os.makedirs(_SOURCE_TEMP,exist_ok=True)


#copy the files

for files in loc_uniq:
    shutil.copy2(files,_SOURCE_TEMP)

#if you want to exclude some files from the copy list

os.chdir(_SOURCE_TEMP)
files = [f for f in os.listdir('.') if os.path.isfile(f)]

for f in files:
    if f.endswith(_EXCLUSION):
        print(f,"ne sera pas copié selon la liste d'exclusion")
        os.remove(f)

#copy the files from the temp repertory to the distant 

with pysftp.Connection(host=_RMTHOST,password=_DESTPASS) as sftp:
    sftp.put_r(_SOURCE_TEMP,_DEST,preserve_mtime=True)

    sftp.close()

这部分脚本在 Win10 上完美运行,列表也在 OSX 上运行(由 Yuri 测试)我第一次遇到错误(在 size = f.stat().st_size,AttributeError: 'int' object has没有属性 'stat') 因为我导入了“时间”模块,请注意这一点。 感谢您 1000 次对 Yuri 的帮助!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。