news 2026/4/17 19:02:28

从samba服务器下载文件工具

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从samba服务器下载文件工具

从 Samba 服务器下载文件工具

启用samba

项目概述

这是一个用于从 Samba 共享服务器下载文件/文件夹的工具,支持批量下载、模块化配置和自定义本地目录结构。

项目结构

get-samba-file/ ├── config.yaml # 配置文件(YAML格式) ├── run.bat # Windows 启动脚本 ├── scripts/ │ └── samba_downloader.py # 主 Python 脚本 ├── doc/ │ └── 从samba服务器下载文件工具.md # 本文档 └── downloads/ # 下载文件存放目录(自动创建) ├── module_name1/ # 按模块名组织的子目录 ├── module_name2/ └── ...

环境要求

系统要求

  • 操作系统:Windows 7/8/10/11
  • Python 版本:3.7 或更高版本

Python 依赖包

脚本需要安装以下 Python 包:

  • PyYAML- 用于解析 YAML 配置文件
  • pysmb- 用于连接 Samba 服务器

安装步骤

1. 安装 Python

如果尚未安装 Python,请从以下地址下载并安装:

  • 下载地址:https://www.python.org/downloads/
  • 推荐版本:Python 3.11+

安装时请勾选 “Add Python to PATH” 选项,将 Python 添加到系统环境变量。

2. 安装依赖包

打开命令提示符(cmd)或 PowerShell,运行以下命令:

python -m pipinstallPyYAML pysmb

或者如果您的系统中有python3命令:

python3 -m pipinstallPyYAML pysmb

3. 验证安装

运行以下命令验证 Python 和依赖包是否正确安装:

python --version python -c"import yaml; import smb; print('依赖包安装成功')"

配置说明

config.yaml 文件结构

配置文件采用 YAML 格式,支持模块化配置。以下是完整的配置示例:

# Samba 服务器模块模板(可选,用于复用配置)module_templates:# 示例:定义一个可复用的模块模板graphic:&graphicname:graphicitems:-path:633/out/arm64/targets/graphic/graphic_2d/# local_name: graphic_2d # 可选:自定义本地目录名# 设备列表devices:# 设备1:192.168.16.17-ip:192.168.16.17share_name:shared_folder_17username:rootpassword:123456modules:-name:kh_edgecomputing_thing_accessmanager_metaitems:-path:kh5.0.1/out/arm64/targets/kh_edgecomputing/kh_edgecomputing_thing_accessmanager_meta/libnanning_subway_handler.z.so# local_name: libnanning_subway_handler.z.so # 可选# 设备2:192.168.16.40-ip:192.168.16.40share_name:shared_folder_40username:rootpassword:123456modules:# 引用模板(推荐)-*graphic-*multimedia-*audio_framework# 或直接定义-name:custom_moduleitems:-path:some/remote/path/local_name:custom_name

配置字段说明

设备级配置(devices[].*)
  • ip:Samba 服务器 IP 地址(必需)
  • share_name:共享目录名称(必需)
  • username:登录用户名(可选,默认为空)
  • password:登录密码(可选,默认为空)
模块级配置(devices[].modules[])
  • name:模块名称,将作为本地下载的根目录名(必需)
  • items:该模块下的文件/目录列表(必需)
项目级配置(devices[].modules[].items[])
  • path:远程 Samba 共享中的路径(必需)
  • local_name:自定义本地文件名/目录名(可选)
    • 如果不指定,将使用远程路径的最后一部分作为本地名称

模板复用

YAML 支持锚点(&)和引用(*)语法,可以定义可复用的模块模板:

module_templates:camera:&cameraname:cameraitems:-path:633/out/arm64/targets/multimedia/camera_framework/devices:-ip:192.168.16.40share_name:shared_folder_40modules:-*camera# 引用模板

使用方法

1. 配置 config.yaml

根据您的 Samba 服务器信息编辑config.yaml文件。

2. 运行脚本

双击run.bat文件,或在命令提示符中运行:

run.bat

3. 交互操作

脚本会显示可用设备列表,用户选择设备后进入功能菜单:

  1. 显示设备完整配置:查看当前设备的详细配置
  2. 检测IP连通性:测试与设备的网络连接
  3. 获取文件/文件夹:下载文件(支持单选或批量下载)
  4. 返回设备选择界面:切换到其他设备
  5. 退出脚本:结束程序

下载规则

  • 目录结构:文件按模块名组织,存放在downloads/模块名/
  • 文件命名
    • 如果设置了local_name,使用自定义名称
    • 否则使用远程路径的最后一部分
  • 目录下载:递归下载整个目录结构
  • 记录文件:每次下载会在目标目录生成info.txt,记录下载信息

故障排除

常见问题

  1. ModuleNotFoundError: No module named ‘yaml’

    • 解决:运行python -m pip install PyYAML pysmb
  2. 连接失败

    • 检查 IP 地址是否正确
    • 确认 Samba 服务正在运行
    • 验证用户名和密码
  3. 权限不足

    • 检查 Samba 共享权限设置
    • 确认用户有读取权限
  4. 中文乱码

    • 脚本已配置 UTF-8 编码,如仍有问题请检查控制台编码

日志查看

下载记录保存在各模块目录的info.txt文件中,包含:

  • 下载时间
  • 远程 IP 和共享名
  • 远程路径
  • 本地保存路径
  • 使用用户名

高级配置

多设备支持

配置文件支持多个设备,脚本会显示设备列表供选择。

批量下载

在文件选择界面输入特殊数字:

  • 0:退出当前界面
  • 所有项目数量 + 1:全部下载

自定义本地名称

通过local_name字段自定义下载后的文件名/目录名。

版本信息

  • 当前版本:v1.0
  • 支持平台:Windows
  • Python 要求:>= 3.7

完整文件内容

为了便于快速部署,以下是完整的文件内容,您可以直接复制创建相应文件。

1. 创建主脚本文件:scripts/samba_downloader.py

首先创建scripts目录,然后创建samba_downloader.py文件:

importsubprocessimportosimportsysimportimportlib.utilfromdatetimeimportdatetime# 新增:用于记录下载时间# 延迟导入 yaml,先给出友好提示try:importyaml# 新增:用于解析yaml文件exceptImportError:print("❌ 缺少依赖:PyYAML")print("👉 请运行:python -m pip install PyYAML pysmb")sys.exit(1)defcheck_environment():"""检测运行环境与依赖,缺失时给出提示"""# Python 版本要求major,minor=sys.version_info[:2]min_major,min_minor=3,7if(major,minor)<(min_major,min_minor):print(f"❌ Python 版本过低,当前{major}.{minor},请升级到 >={min_major}.{min_minor}")sys.exit(1)# 必需依赖requirements=[("yaml","PyYAML"),("smb.SMBConnection","pysmb"),]missing=[]formod,pip_nameinrequirements:ifimportlib.util.find_spec(mod)isNone:missing.append(pip_name)ifmissing:miss_str=", ".join(missing)pip_cmd=f"python -m pip install{' '.join(missing)}"print(f"❌ 缺少依赖:{miss_str}")print(f"👉 请运行安装命令:{pip_cmd}")sys.exit(1)else:print(f"✅ 环境检查通过:Python{major}.{minor},依赖齐全")defread_device_config():""" 读取yaml格式的设备配置文件,返回设备列表(包含IP、模块、路径及凭据) 期望文件:config.yaml """config_path=os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),"config.yaml")ifnotos.path.exists(config_path):print("❌ 未找到配置文件,请在脚本同目录创建 'config.yaml',示例:")print(""" devices: - ip: 192.168.16.40 share_name: shared_folder_40 username: root password: 123456 modules: - name: camera items: - path: 633/out/arm64/targets/multimedia/camera_framework/ local_name: camera_framework # 可选:自定义本地目录/文件名 - path: 001/out/tr12/multimedia/audio_framework/libaudio_service.z.so - name: graphic items: - path: 633/out/arm64/targets/graphic/graphic_2d/ """)sys.exit(1)try:withopen(config_path,"r",encoding="utf-8")asf:raw=yaml.safe_load(f)or{}exceptExceptionase:print(f"❌ 读取 'config.yaml' 失败:{e}")sys.exit(1)if"devices"notinrawornotisinstance(raw["devices"],list)ornotraw["devices"]:print("❌ 配置错误:config.yaml 中未找到 devices 列表")sys.exit(1)devices=[]fordevinraw["devices"]:ip=dev.get("ip")share_name=dev.get("share_name")modules=dev.get("modules",[])ifnotipornotshare_name:print("❌ 配置错误:每个设备必须包含 ip 与 share_name")sys.exit(1)ifnotisinstance(modules,list)ornotmodules:print(f"❌ 配置错误:设备{ip}未配置 modules 或 modules 为空")sys.exit(1)normalized_modules=[]formodinmodules:mod_name=mod.get("name")items=mod.get("items",[])ifnotmod_name:print(f"❌ 配置错误:设备{ip}的某个模块缺少 name")sys.exit(1)ifnotisinstance(items,list)ornotitems:print(f"❌ 配置错误:设备{ip}的模块{mod_name}缺少 items 列表")sys.exit(1)normalized_items=[]foriteminitems:path=item.get("path")ifnotpath:print(f"❌ 配置错误:设备{ip}的模块{mod_name}存在缺少 path 的条目")sys.exit(1)normalized_items.append({"path":path,"local_name":item.get("local_name","").strip()orNone})normalized_modules.append({"name":mod_name,"items":normalized_items})# 扁平化目标列表,便于展示和选择targets=[]formodinnormalized_modules:foriteminmod["items"]:targets.append({"module":mod["name"],"path":item["path"],"local_name":item.get("local_name")})devices.append({"ip":ip,"share_name":share_name,"modules":normalized_modules,"targets":targets,# 确保用户名/密码为字符串,避免解析为数字导致 pysmb 报错"username":str(dev.get("username","")or""),"password":str(dev.get("password","")or"")})returndevicesdefping_ip(ip):"""ping指定IP,返回是否连通(Windows系统)"""try:result=subprocess.run(["ping","-n","2","-w","1000",ip],stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)returnresult.returncode==0exceptExceptionase:print(f"⚠️ ping检测出错:{str(e)}")returnFalsedefselect_device(devices):"""让用户选择要连接的设备(显示IP及关键参数)"""print("\n📋 可用设备列表:")fori,devinenumerate(devices,1):print("--------------------------------------")print(f"{i}. IP:{dev['ip']}")# 按模块分行展示目标module_targets={}fortindev["targets"]:display_name=t.get("local_name")oros.path.basename(t["path"].rstrip('/\\'))ort["path"]module_targets.setdefault(t["module"],[]).append(display_name)total_targets=sum(len(v)forvinmodule_targets.values())print(f" 共享目录:{dev['share_name']}| 目标项:{total_targets}个")print(" 目标预览:")formodule,namesinmodule_targets.items():print(f" [{module}]{', '.join(names)}")print("--------------------------------------")whileTrue:try:choice=input(f"\n请输入要连接的设备序号(1-{len(devices)}):")ifnotchoice.isdigit():print("❌ 请输入数字!")continueindex=int(choice)-1if0<=index<len(devices):returndevices[index]else:print(f"❌ 序号超出范围,请输入1到{len(devices)}之间的数字!")exceptExceptionase:print(f"⚠️ 选择出错:{str(e)},请重新输入")deffunction_menu(selected_device,is_single_device=False):"""功能菜单(显示设备完整参数及所有远程路径)"""ip=selected_device["ip"]print(f"\n✅ 已选择设备:{ip},进入功能菜单:")# 恢复这条打印,确保一致性whileTrue:print("\n-------------------")print("1. 显示设备完整配置")print("2. 检测IP连通性")print("3. 获取文件/文件夹")ifnotis_single_device:print("4. 返回设备选择界面")last_option_num=5else:last_option_num=4# 如果没有"返回设备选择界面",则"退出脚本"是第4个选项print(f"{last_option_num}. 退出脚本")print("-------------------")try:func_choice=input(f"请选择功能(1-{last_option_num}):")ifnotfunc_choice.isdigit():print("❌ 无效选择,请输入数字!")continuechoice_int=int(func_choice)ifchoice_int==1:print("\n设备完整配置:")print(f" IP:{selected_device['ip']}")print(f" 共享目录:{selected_device['share_name']}")print(" 远程文件路径列表:")fori,tinenumerate(selected_device['targets'],1):display_name=t.get("local_name")oros.path.basename(t["path"].rstrip('/\\'))ort["path"]print(f" 路径{i}:[{t['module']}]{t['path']}-> 本地名:{display_name}")print(f" 用户名:{selected_device['username']or'未设置'}")print(f" 密码:{'*'*len(selected_device['password'])ifselected_device['password']else'未设置'}")# 密码脱敏elifchoice_int==2:is_alive=ping_ip(ip)status="正常"ifis_aliveelse"中断"print(f"\n{ip}连通性检测:{status}")elifchoice_int==3:handle_file_retrieval(selected_device)elifchoice_int==4andnotis_single_device:# 多设备时的"返回设备选择界面"print("\n返回设备选择界面...")return# 返回到main函数中的设备选择循环elifchoice_int==last_option_num:# 退出脚本 (单设备或多设备的退出选项)print("\n👋 退出脚本,再见!")sys.exit(0)else:print(f"❌ 无效选择,请输入1-{last_option_num}之间的数字!")exceptExceptionase:print(f"⚠️ 功能执行出错:{str(e)}")defhandle_file_retrieval(selected_device):"""处理文件/文件夹的获取逻辑"""ip=selected_device["ip"]share_name=selected_device["share_name"]targets=selected_device["targets"]username=selected_device["username"]password=selected_device["password"]local_base_dir="./downloads"os.makedirs(local_base_dir,exist_ok=True)# 确保本地下载目录存在whileTrue:print(f"\n📦 可获取的文件/文件夹列表(来自{ip}/{share_name}):")fori,tinenumerate(targets,1):display_name=t.get("local_name")oros.path.basename(t["path"].rstrip('/\\'))ort["path"]print(f"{i}. [{t['module']}]{t['path']}-> 本地:{t['module']}/{display_name}")print(f"{len(targets)+1}. 全部获取")print(" 0. 退出当前界面")# 新增退出选项try:choice=input(f"\n请输入要获取的序号(0-{len(targets)+1}):")ifnotchoice.isdigit():print("❌ 请输入数字!")continueindex=int(choice)-1ifindex==-1:# 用户选择了退出print("返回功能菜单...")break# 退出当前循环,返回上一级菜单elif0<=index<len(targets):# 用户选择了特定文件/文件夹target=targets[index]print(f"开始获取:[{target['module']}]{target['path']}")download_samb_item(ip,share_name,target["path"],local_base_dir,username,password,target["module"],target.get("local_name"))# 操作完成后不退出,继续显示当前菜单elifindex==len(targets):# 用户选择了全部获取print("开始获取所有配置的文件/文件夹...")fortargetintargets:download_samb_item(ip,share_name,target["path"],local_base_dir,username,password,target["module"],target.get("local_name"))print("所有文件/文件夹获取完成!")# 操作完成后不退出,继续显示当前菜单else:print(f"❌ 序号超出范围,请输入0到{len(targets)+1}之间的数字!")exceptExceptionase:print(f"⚠️ 选择出错:{str(e)},请重新输入")defdownload_samb_item(ip,share_name,remote_path,local_base_dir,username,password,module_name,local_name=None):"""从Samba共享下载文件或文件夹 (使用pysmb库),支持模块根目录与自定义本地名"""try:fromsmb.SMBConnectionimportSMBConnectionfromsmb.smb_structsimportOperationFailureexceptImportError:print("❌ 缺少 'pysmb' 库。请运行 'pip install pysmb' 进行安装。")returnconn=Nonetry:# 创建连接client_machine_name="PythonClient"server_name=ip# 确保凭据为字符串,避免 int 类型引发 encode 错误conn=SMBConnection(str(usernameor""),str(passwordor""),client_machine_name,server_name)ifnotconn.connect(ip,445):print(f"❌ 无法连接到 Samba 共享{ip}:445。请检查IP、用户名、密码和网络连接。")return# 确定本地保存路径remote_path_cleaned=remote_path.replace('\\','/')# 首先获取远程路径的属性,以确定是文件还是目录is_directory=Falsetry:smb_remote_path=remote_path_cleaned file_attrs=conn.getAttributes(share_name,smb_remote_path)is_directory=file_attrs.isDirectoryexceptOperationFailurease:print(f"❌ 远程路径 '{remote_path}' 不存在或无法访问。错误:{e}")returnmodule_dir=os.path.join(local_base_dir,module_name)ifis_directory:# 如果是文件夹,本地路径是 downloads/<模块名>/<自定义名或远程目录名>target_dir_name=local_nameoros.path.basename(remote_path_cleaned.rstrip('/'))local_path=os.path.join(module_dir,target_dir_name)print(f"从 '{ip}/{share_name}/{remote_path}' 下载文件夹到 '{local_path}\\'...")_download_samba_directory(conn,share_name,remote_path_cleaned,local_path)print(f"✅ 文件夹 '{remote_path}' 下载完成!")_write_download_info(ip,share_name,remote_path,local_path,username,module_name,is_directory=True)else:# 如果是文件,本地路径是 downloads/<模块名>/<自定义名或文件名>file_name=local_nameoros.path.basename(remote_path_cleaned)local_path=os.path.join(module_dir,file_name)print(f"从 '{ip}/{share_name}/{remote_path}' 下载文件到 '{local_path}'...")os.makedirs(os.path.dirname(local_path),exist_ok=True)withopen(local_path,'wb')aslocal_file:conn.retrieveFile(share_name,smb_remote_path,local_file)print(f"✅ 文件 '{remote_path}' 下载完成!")_write_download_info(ip,share_name,remote_path,local_path,username,module_name,is_directory=False)exceptOperationFailurease:# 捕获更具体的Samba操作失败,例如认证失败或权限不足ife.ntStatus==0xC0000022:# STATUS_ACCESS_DENIEDprint(f"❌ Samba权限不足或认证失败:请检查config.yaml中的用户名和密码,以及Samba服务器上的用户权限。错误:{e}")elif"LOGON_FAILURE"instr(e):print(f"❌ Samba认证失败:用户名或密码错误。请检查config.yaml配置。错误:{e}")else:print(f"❌ Samba操作失败:{e},请检查远程路径是否存在或权限。")exceptExceptionase:print(f"⚠️ 获取文件/文件夹时发生未知错误:{str(e)}")finally:ifconn:conn.close()def_download_samba_directory(conn,share_name,remote_dir,local_dir):os.makedirs(local_dir,exist_ok=True)file_list=conn.listPath(share_name,remote_dir.replace(os.sep,'/'))forfinfile_list:iff.filenamein['.','..']:continuecurrent_remote_path=f"{remote_dir.rstrip('/')}/{f.filename}"current_local_path=os.path.join(local_dir,f.filename)iff.isDirectory:_download_samba_directory(conn,share_name,current_remote_path,current_local_path)else:print(f" 下载文件:{current_remote_path}->{current_local_path}")os.makedirs(os.path.dirname(current_local_path),exist_ok=True)withopen(current_local_path,'wb')aslocal_file:conn.retrieveFile(share_name,current_remote_path.replace(os.sep,'/'),local_file)def_write_download_info(ip,share_name,remote_path,local_path,username,module_name,is_directory=False):"""将下载信息写入文件/文件夹的同级目录"""ifis_directory:info_dir=local_pathelse:info_dir=os.path.dirname(local_path)os.makedirs(info_dir,exist_ok=True)download_info_file=os.path.join(info_dir,"info.txt")# 使用追加模式,每次下载都添加信息withopen(download_info_file,'a',encoding='utf-8')asf:f.write(f"[下载信息 -{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]\n")f.write(f"远程 IP:{ip}\n")f.write(f"Samba 共享名:{share_name}\n")f.write(f"远程路径:{remote_path}\n")f.write(f"本地保存路径:{local_path}\n")f.write(f"模块:{module_name}\n")f.write(f"用户名:{username}\n")f.write("-"*30+"\n")defmain():print("===== 设备连接工具 =====")check_environment()# 读取设备配置(包含IP及关联参数)devices=read_device_config()whileTrue:iflen(devices)==1:selected_device=devices[0]# 如果是单设备,跳过设备选择提示,但仍进行连通性检测print(f"\n正在检测{selected_device['ip']}连通性...")ifping_ip(selected_device['ip']):function_menu(selected_device,is_single_device=True)# 如果从function_menu返回(用户选择了返回设备选择界面),且只有一个设备,则退出print("👋 脚本退出,再见!")sys.exit(0)else:print(f"❌{selected_device['ip']}连接失败(ping不通),脚本退出。")sys.exit(1)else:# 多个设备,需要用户选择selected_device=select_device(devices)print(f"\n正在检测{selected_device['ip']}连通性...")ifping_ip(selected_device['ip']):function_menu(selected_device,is_single_device=False)# 如果从function_menu返回(用户选择了返回设备选择界面),则继续外层循环,让用户重新选择设备else:print(f"❌{selected_device['ip']}连接失败(ping不通),请重新选择")if__name__=="__main__":main()

2. 创建配置文件:config.yaml

创建项目根目录下的config.yaml文件:

# 配置范例说明(新手友好):# - module_templates: 复用的模块模板,锚点名以 & 开头,引用时用 * 锚点名# - name: 模块名(同时作为本地下载的顶层目录)# - items: 要下载的文件/目录列表# - path: 远程路径(相对 Samba 共享根)# - local_name: 可选,自定义下载到本地的文件/目录名(不填则用远程 basename)# - devices: 设备列表# - ip: 设备 IP# - share_name: Samba 共享名# - username/password: 登录凭据# - modules: 此设备要下载的模块;可直接写模块定义,也可引用模板(如 *graphic)module_templates:# 如下载目录,则 name 可设为目录父级;如下载文件,则 name 可设为文件父目录xwdvk_d2000_small:&xwdvk_d2000_smallname:xwdvk_d2000_smallitems:-path:0/litea/out/xwdvk_d2000_small/xwdvk_d2000_small/usr/lib/libavfilter.solocal_name:libavfilter.so-path:0/litea/out/xwdvk_d2000_small/xwdvk_d2000_small/bin/opdemo_demolocal_name:opdemo_demo.bin-path:0/litea/out/xwdvk_d2000_small/xwdvk_d2000_small/rootfs/lib/libc.solocal_name:libc.sographic:&graphicname:graphicitems:-path:633/out/arm64/targets/graphic/graphic_2d/# local_name: graphic_2d # 可选:指定本地目录名multimedia:&multimedianame:multimediaitems:-path:633/out/arm64/targets/multimedia/camera_framework/# local_name: camera_frameworkaudio_framework:&audio_frameworkname:audio_frameworkitems:-path:001/out/tr12/multimedia/audio_framework/libaudio_service.z.so-path:001/out/tr12/multimedia/audio_framework/libaudio_policy_service.z.sokh_distributed_input:&kh_distributed_inputname:distributedhardwareitems:-path:001/out/arm64/targets/kh_distributed/kh_distributed_screen_input/kh_distributed_screen:&kh_distributed_screenname:distributedhardwareitems:-path:001/out/arm64/targets/kh_distributed/kh_distributed_screen/633camera:&633cameraname:633cameraitems:-path:633/out/arm64/targets/hdf/drivers_peripheral_camera/libusb_camera_pipeline_core.z.so-path:633/out/arm64/targets/hdf/drivers_peripheral_camera/libcamera_daemon.so-path:633/out/arm64/targets/multimedia/camera_framework/libcamera_service.z.so-path:633/out/arm64/targets/graphic/graphic_2d/librender_service.z.sodevices:-ip:192.168.16.17share_name:shared_folder_17username:rootpassword:123456modules:-name:kh_edgecomputing_thing_accessmanager_metaitems:-path:kh5.0.1/out/arm64/targets/kh_edgecomputing/kh_edgecomputing_thing_accessmanager_meta/libnanning_subway_handler.z.so# local_name: 自定义本地文件名,可选-*kh_distributed_screen-*kh_distributed_input-ip:192.168.16.40share_name:shared_folder_40username:rootpassword:123456modules:#- *graphic#- *multimedia#- *audio_framework-*633camera

3. 创建启动脚本:run.bat

创建项目根目录下的run.bat文件:

@echo off chcp 65001 >nul 2>&1 set "PYTHONUTF8=1" set "PYTHONIOENCODING=utf-8" set "script_dir=%~dp0" set "py_script=%script_dir%scripts\samba_downloader.py" if not exist "%py_script%" ( echo ERROR: samba_downloader.py not found in current folder. pause exit /b 1 ) where python >nul 2>&1 if %errorlevel% equ 0 ( set "python_cmd=python" ) else ( where python3 >nul 2>&1 if %errorlevel% equ 0 ( set "python_cmd=python3" ) else ( echo ERROR: Python not found. Install Python and add to PATH. echo Download: https://www.python.org/downloads/ pause exit /b 1 ) ) echo Starting samba_downloader.py ... echo ============================== "%python_cmd%" "%py_script%" echo ============================== echo Script finished. Press any key to exit... pause >nul

文件创建步骤

  1. 创建目录结构

    mkdirscriptsmkdirdoc
  2. 创建文件

    • 将上述第一个代码块内容保存为scripts/samba_downloader.py
    • 将上述第二个代码块内容保存为config.yaml
    • 将上述第三个代码块内容保存为run.bat
  3. 安装依赖

    python -m pipinstallPyYAML pysmb
  4. 运行脚本
    双击run.bat启动工具

更新日志

  • v1.0:初始版本,支持基本下载功能和 YAML 配置
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 11:27:30

企业IT管理员必看:kb2919355补丁部署实战

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个企业级补丁管理工具&#xff0c;专门针对kb2919355补丁的批量部署。功能包括&#xff1a;1. 多台计算机远程检测补丁状态&#xff1b;2. 批量下载和安装补丁&#xff1b;3.…

作者头像 李华
网站建设 2026/4/15 17:36:55

联想LJ2605D与LJ2655DN激光打印机专业维护指南

联想LJ2605D与LJ2655DN激光打印机专业维护指南 【免费下载链接】联想LJ2605DLJ2655DN中文维修手册分享 联想LJ2605D LJ2655DN中文维修手册欢迎来到联想LJ2605D与LJ2655DN激光打印机的中文维修手册下载页面 项目地址: https://gitcode.com/Open-source-documentation-tutorial…

作者头像 李华
网站建设 2026/4/16 12:29:28

对比评测:3种VS Code汉化方案效率提升300%

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个VS Code汉化效率对比工具&#xff0c;要求&#xff1a;1. 自动记录三种汉化方式的操作步骤和时间 2. 生成可视化对比图表 3. 计算节省的工时 4. 分析错误率差异 5. 输出优化…

作者头像 李华
网站建设 2026/4/16 13:54:47

Voice有声书播放神器:重新定义你的听书体验

还在为繁琐的有声书播放器而烦恼吗&#xff1f;Voice这款极简主义有声书播放器&#xff0c;绝对是你的听书救星&#xff01;它不仅仅是一个播放器&#xff0c;更像是一个懂你的声音管家。 【免费下载链接】Voice Minimalistic audiobook player 项目地址: https://gitcode.co…

作者头像 李华
网站建设 2026/4/16 13:38:35

11、Apache服务器高级配置与优化技巧

Apache服务器高级配置与优化技巧 在Apache服务器的使用过程中,有许多实用的技巧和方法可以帮助我们更好地管理和优化服务器性能。下面将详细介绍一些重要的配置和优化技巧。 重写日志配置 要在其他默认Apache日志文件旁边启用重写日志,可以使用以下配置: RewriteLog “…

作者头像 李华
网站建设 2026/4/16 14:16:09

12、Apache 与 PHP 的安全配置及应用指南

Apache 与 PHP 的安全配置及应用指南 在当今数字化的时代,网站的安全性和性能优化是至关重要的。Apache 作为一款强大的 Web 服务器软件,与 PHP 结合使用,能够为我们提供丰富的功能和强大的性能。下面将详细介绍 Apache 的一些关键配置和功能,以及如何利用 PHP 来增强网站…

作者头像 李华