You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现从远程SFTP服务器仅下载无本地同名(忽略扩展名)新文件

SFTP文件拉取脚本修正方案

需求规则

实现Python脚本从远程SFTP服务器拉取文件到本地目录,下载前需做文件名匹配校验,校验规则为忽略文件扩展名,仅对比文件名主体:

  • 本地目录已存在相同文件名主体的文件时,无论远程文件与本地文件的扩展名是否一致,均不下载该远程文件
  • 示例场景:远程服务器目录下存在abc.xlsx、abc.csv、adc.txt三个文件,本地目录已存在abc.xlsx,则所有文件名为abc主体的远程文件(abc.xlsx、abc.csv)均无需下载,仅下载本地无对应同名主体的adc.txt

原有代码逻辑缺陷

  • 嵌套循环遍历本地文件时,只要遇到一个文件名主体不匹配的本地文件就会触发下载,会导致同一个远程文件被重复触发下载多次,无法实现「本地只要存在任意一个同主体文件就跳过」的规则
  • 错误使用sftp.listdir()读取本地目录,该方法仅能读取SFTP远程路径内容,本地目录列表需要用os.listdir()获取
  • 未过滤远程路径下的子目录,会尝试下载文件夹触发运行报错
  • 导入了多个未使用的冗余模块

修正后可运行代码

import os
import pysftp

# SFTP连接配置
Hostname = "Hostname"
Username = "Username"
Password = "Password"
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None

# 路径配置
local_dir = r"D:\testing"
remote_dir = r'C:\Users\admin\Documents\personal'

if __name__ == "__main__":
    # 提前扫描本地目录,收集所有已存在文件的文件名主体(自动去重)
    local_file_stems = set()
    for local_entry in os.listdir(local_dir):
        local_full_path = os.path.join(local_dir, local_entry)
        # 仅统计本地普通文件,跳过子目录
        if os.path.isfile(local_full_path):
            file_stem = os.path.splitext(local_entry)[0]
            local_file_stems.add(file_stem)
    
    with pysftp.Connection(host=Hostname, username=Username, password=Password,
                           cnopts=cnopts) as sftp:
        print("SFTP连接建立成功 ... ")
        # 遍历远程目录条目
        for remote_entry in sftp.listdir(remote_dir):
            remote_full_path = os.path.join(remote_dir, remote_entry)
            # 跳过远程目录下的子文件夹,仅处理文件
            if sftp.isdir(remote_full_path):
                continue
            # 获取远程文件的文件名主体
            remote_stem = os.path.splitext(remote_entry)[0]
            # 本地已存在同主体文件直接跳过
            if remote_stem in local_file_stems:
                print(f"跳过已存在同主体文件:{remote_entry}")
                continue
            # 不存在对应主体文件则执行下载
            local_save_path = os.path.join(local_dir, remote_entry)
            sftp.get(remote_full_path, local_save_path, preserve_mtime=False)
            print(f"下载完成:{remote_entry}")

核心修改点

  • 提前一次性扫描本地目录,将所有本地文件的文件名主体存入set集合做去重,后续校验直接做集合成员判断,无需嵌套循环,既提升运行效率,也避免了原有逻辑里只要遇到一个不匹配的本地文件就触发下载的错误
  • 修正本地目录读取方式:本地文件列表用os.listdir()获取,仅远程路径用sftp.listdir()读取,解决原有代码错误调用SFTP方法读本地路径的问题
  • 新增文件类型过滤:遍历本地和远程路径时都自动跳过子目录,仅处理普通文件,避免尝试下载文件夹触发报错
  • 严格实现校验规则:只要远程文件的文件名主体存在于本地已收集的主体集合中,无论两者扩展名是否一致,都直接跳过下载,完全匹配需求要求

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:01:18