You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python与rsync:如何处理重名文件问题?

解决远程相机会话重名文件的rsync+Python自动化方案

嘿,这个场景我之前帮朋友处理过类似的情况——远程相机重启会话后生成的重名文件确实会给同步和归档带来麻烦。核心思路就是给每个会话的文件加上唯一标识,再用Python自动化整个流程,结合rsync完成上传和外置HDD归档。下面是具体的实现方案:

一、核心逻辑拆解

  1. 识别会话边界:相机重启应用后,新生成的文件虽然文件名重复,但它们的创建时间会和上一个会话的最后一个文件有明显间隔(比如重启应用的几分钟空档),我们可以用这个时间差来区分不同会话。
  2. 给会话文件做唯一标记:要么给每个会话创建独立的子目录,要么直接给文件名加上会话ID/时间戳前缀,确保不管文件名怎么重复,整体路径是唯一的。
  3. Python调用rsync自动化执行:用Python的subprocess模块调用rsync命令,完成上传到远程服务器、移动到外置HDD的操作,同时还能校验命令执行结果,避免出错。

二、具体实现步骤

1. 监控新文件并区分会话

我们可以用Python监控相机照片的存储目录,当新文件到来时,通过时间差判断是否属于新会话:

  • 记录上一个文件的修改时间,如果当前文件和上一个文件的时间差超过阈值(比如5分钟,可根据实际情况调整),则判定为新会话。
  • 用时间戳作为会话ID,确保每个会话的标识唯一。
import os
import time
from datetime import datetime
import shutil

# 相机照片的原始存储目录
SOURCE_DIR = "/path/to/camera/photos"
# 临时归类会话文件的目录
SESSION_BASE_DIR = "/path/to/session/files"

# 会话时间间隔阈值(秒),超过这个时间判定为新会话
SESSION_GAP_THRESHOLD = 300  # 5分钟

last_file_mtime = 0
current_session_id = None
current_session_dir = None

def get_session_id():
    # 用当前时间戳作为会话ID,确保全局唯一
    return datetime.now().strftime("%Y%m%d_%H%M%S")

while True:
    # 获取目录下的所有JPG文件,按修改时间排序
    files = sorted(
        [f for f in os.listdir(SOURCE_DIR) if f.lower().endswith(".jpg")],
        key=lambda x: os.path.getmtime(os.path.join(SOURCE_DIR, x))
    )
    
    for file in files:
        file_path = os.path.join(SOURCE_DIR, file)
        file_mtime = os.path.getmtime(file_path)
        
        # 判断是否触发新会话
        if file_mtime - last_file_mtime > SESSION_GAP_THRESHOLD or current_session_id is None:
            current_session_id = get_session_id()
            current_session_dir = os.path.join(SESSION_BASE_DIR, current_session_id)
            os.makedirs(current_session_dir, exist_ok=True)
            print(f"新会话启动:{current_session_id}")
        
        # 将文件移动到当前会话专属目录
        dest_path = os.path.join(current_session_dir, file)
        if not os.path.exists(dest_path):
            shutil.move(file_path, dest_path)
            print(f"移动文件到会话目录:{file} -> {current_session_dir}")
        
        last_file_mtime = file_mtime
    
    # 每隔10秒检查一次新文件
    time.sleep(10)

2. 调用rsync完成上传和归档

在文件归类到会话目录后,我们可以扩展代码,调用rsync完成远程上传和外置HDD归档:

import subprocess

# 远程服务器信息(格式:用户@主机:目标路径)
REMOTE_SERVER = "user@remote-host:/path/to/remote/storage"
# 外置HDD的存储目录
EXTERNAL_HDD_DIR = "/path/to/external/hdd/storage"

def run_rsync_command(cmd):
    # 执行rsync命令并返回执行结果
    try:
        result = subprocess.run(cmd, shell=True, check=True, capture_output=True, text=True)
        print(f"命令执行成功:{cmd}")
        return True
    except subprocess.CalledProcessError as e:
        print(f"命令执行失败:{cmd},错误信息:{e.stderr}")
        return False

def process_session(session_dir):
    # 1. 上传会话目录到远程服务器
    upload_cmd = f"rsync -avz {session_dir}/ {REMOTE_SERVER}/{os.path.basename(session_dir)}/"
    if not run_rsync_command(upload_cmd):
        return False
    
    # 2. 将会话目录移动到外置HDD(--remove-source-files实现移动效果)
    archive_cmd = f"rsync -avz --remove-source-files {session_dir}/ {EXTERNAL_HDD_DIR}/{os.path.basename(session_dir)}/"
    if run_rsync_command(archive_cmd):
        # 删除空的会话目录
        os.rmdir(session_dir)
        print(f"会话归档完成:{session_dir}")
        return True
    return False

3. 整合完整流程

你可以把会话监控和处理逻辑整合:当一个会话结束(比如超过阈值时间没有新文件到来),就触发上传和归档操作;或者设置定时任务,每隔一段时间处理已经完成的会话目录,避免占用本地空间。

三、额外优化建议

  • 错误重试机制:如果rsync上传失败,可以添加重试逻辑(比如最多重试3次),避免文件同步失败。
  • 日志记录:将所有操作记录到日志文件,方便后续排查问题。
  • 文件校验:上传时可以添加--checksum参数,让rsync通过校验和验证文件完整性,确保上传的文件和源文件一致。
  • 并发处理:如果同时有多个会话需要处理,可以用多线程同时执行不同会话的上传操作,提升效率(注意控制线程数量,避免占用过多带宽)。

内容的提问来源于stack exchange,提问作者rvrvrv

火山引擎 最新活动