【发布时间】:2021-06-26 22:01:22
【问题描述】:
对于一个学生项目,我构建了一个脚本,仅将“新”文件复制到遥远的目录。 我能够找到远程文件夹中不存在的文件并将其复制,它正在工作。 现在,我尝试复制具有相同名称但大小或修改日期不同的文件。
我可以创建一个包含所有需要信息的本地文件列表:
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, 'blabla.txt')
(143897, 1583941480, 'Projet4_configuration_navigateur_proxy01.jpg')
(0, 1624520128, 'testcopie.txt')
-
本地列表中的 mtime 返回一个浮点数,而不是远距离的,我认为无法正确比较这些数字。
-
我找不到一个可行的解决方案来比较这些文件列表,我尝试了很多解决方案,以及“不太糟糕”的解决方案:
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: ", _SOURCE, "est valide et accessible \n \n")
else:
print("le dossier source: ", _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, 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)
#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, time, name)] = f
# get lists of unique files based on keys (size,time,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, username=_USR, password=_DESTPASS) as sftp:
sftp.put(_SOURCE_TEMP, _DEST, 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, 1622736305.82416, '20_060_12C_24T_3800_AMD_Ryzen_9_3900X_12_Core_Processor_64_Bit.txt')
(9602, 1624743218.308332, 'blabla.txt')
(46, 1624736892.7385924, 'desktop.ini')
(143897, 1583941480.0, 'Projet4_Jeremie_Voita_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, 'blabla.txt')
(143897, 1583941480, 'Projet4_Jeremie_Voita_configuration_navigateur_proxy01.jpg')
(0, 1624520128, '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
【问题讨论】:
-
1.为什么不直接使用 SSH 运行 python 命令呢?您通过 SSH 连接,然后调用 SFTP 函数来检索统计信息,这听起来有点矫枉过正。 2. 比较建议:可以使用字典,而Key就是文件名,每个key根据文件大小可能是另一个字典。因此,Miss 意味着文件存在差异或它们不存在。让我知道您是否可以按照上述建议继续前进
-
我可能在目录中有大量文件,我认为通过 SSh 会更慢?另外,我尝试了这个解决方案,但是我不能使用带有遥远目录的基本比较模块,它总是返回错误。当然我认为有些解决方案是存在的,但我是初学者,我试图将我的脚本保留为尽可能简单。我会研究一下字典,谢谢你的建议
标签: python list file difference