标题: [FTP] 普遍适用的FTP文件夹上传下载批处理函数 [打印本页]
作者: Spring 时间: 2011-9-5 23:55 标题: 普遍适用的FTP文件夹上传下载批处理函数
之前有说FTP的mput和mget命令能上传下载文件夹,但是不能对子文件夹进行操作,这里给出的两个函数 FTPXPut 和 FTPXGet 可以递归操作子文件夹里面的文件。
过程从会在临时文件夹生成一些文件,之后会自动删除。
注意:你可以修改指定部位的代码,达到更个性化的目的,因为他们已经精确到了对每个文件夹和文件的操作,具体位置详见注释。
下面是一个在批处理文件中调用它们的实例,两个下载的例子可以直接运行,因为是访问公共资源;上传的例子需要自己修改,如果你有某个FTP服务器的帐号。
ftpXgetXput_sample.bat 链接: https://pan.baidu.com/s/1iQ1AlKS1xsOiVhlqLnZVGA?pwd=qqdt- @echo off
- REM 上传下载测试(匿名用户 anonymous 密码任意)
- REM 下载一个 UNIX 目录列表类型服务器上的文件夹
- echo ***************** 开始从 UNIX 服务器下载文件夹 **************************
- set rp=/pub/mirrors/ubuntu/pool/main/l/language-pack-zh/
- call :FTPXGet ftp.cs.stanford.edu anonymous Spring %rp% .\zh
- pause
- REM 下载一个 MS-DOS 目录列表类型服务器上的文件夹
- echo ***************** 开始从 WINDOWS 服务器下载文件夹 ***********************
- set rp=/Products/Windows/Windows95/CDRomExtras/AdministrationTools/
- call :FTPXGet ftp.microsoft.com anonymous Brother %rp% D:\ms
- pause
- echo ***************** 开始上传文件夹到远程 FTP 服务器 ***********************
- call :FTPXPut 10.120.6.43 was1 admin "%userprofile%\Favorites" /MyFavoriteSites
- pause
- goto :EOF
-
-
-
- REM 上传一个本地文件夹到 FTP 服务器
- REM ============================================================================
- REM [FTPXPut] (C)2011 Spring
- REM 将一个本地文件夹 %4 上传为 FTP 服务器 %1 的 %5 文件夹,用户名 %2,密码 %3。
- REM 你可以修改 Folder Operation 和 File Operation 的内容达到个性化的目的。
- REM ============================================================================
- :FTPXPut
- if [%5]==[] (
- echo ERROR : 参数不足,已退出。
- goto :EOF
- )
- setlocal enabledelayedexpansion
- REM 存放 FTP 命令行的临时文件
- set $__ftpq="%temp%\CommandQueue%random%.txt"
- REM 本地文件夹绝对路径,以 "\" 结尾
- set $__ldir=%~f4\
- set $__ldir=!$__ldir:\\=\!
- REM 远程文件夹绝对路径,以 "/" 结尾
- set $__rdir=/%5/
- set $__rdir=!$__rdir:\=/!
- set $__rdir=!$__rdir:"=!
- set $__rdir=!$__rdir://=/!
- REM 检测基本条件
- echo 本地目录:!$__ldir!
- echo 远程目录:!$__rdir!
- echo 初始化...
- if not exist "!$__ldir!" (
- echo ERROR : 找不到文件夹 "!$__ldir!",已退出。
- goto :EOF
- )
- REM 本地文件夹顶层目录的长度,在获取相对路径时会用到
- set /a LEN_SKIP=0
- for /l %%i in (0,1,1000) do (
- if not "!$__ldir:~%%i,1!"=="" (
- set /a LEN_SKIP+=1
- )
- )
- REM 创建 FTP 命令行文件并写入登录命令和建立目标顶层文件夹的命令
- (echo open %1
- echo %2
- echo %3
- echo binary)>!$__ftpq!
- echo 正在映射文件夹并添加FTP传输队列...
- REM 先进行文件夹及子文件夹查询
- for /f "delims=" %%a in ('echo !$__ldir!^&dir /s /b /ad "!$__ldir!"') do (
- REM 当前本地路径
- set "$__lcp=%%a\"
- set "$__lcp=!$__lcp:\\=\!"
- REM 相对路径
- set "$__lcrp=!$__lcp:~%LEN_SKIP%!"
- REM 最顶层的文件夹路径全被截掉了,因此加个判断避免出错
- if not "!$__lcrp!"=="" set "$__lcrp=!$__lcrp:\=/!"
- echo !$__lcp! --^> !$__rdir!!$__lcrp!
- REM 添加建立远程文件夹并将远程目录切换至此文件夹的命令
- REM ==================== Folder Operation ====== Start =====================
- echo mkdir "!$__rdir!!$__lcrp!">>!$__ftpq!
- echo cd "!$__rdir!!$__lcrp!">>!$__ftpq!
- REM ==================== Folder Operation ====== End =====================
- REM 对每个子文件夹进行文件查询并生成操作命令
- for /f "delims=" %%z in ('dir /b /a-d "!$__lcp!" 2^>nul') do (
- REM ================= File Operation ====== Start ======================
- echo put "!$__lcp!%%z">>!$__ftpq!
- REM ================= File Operation ====== End ======================
- )
- )
- REM 写入退出 FTP 的命令
- echo bye>>!$__ftpq!
- REM 启动传输过程
- echo 启动FTP文件传输队列...
- ftp -v -s:!$__ftpq!
- echo 文件传输完成。
- REM 清除过程中产生的临时文件
- echo 正在清除临时文件...
- del !$__ftpq!
- echo 操作完成。
- endlocal
- goto :EOF
-
-
- REM 下载一个 FTP 文件夹到本地
- REM ============================================================================
- REM [FTPXGet] (C)2011 Spring
- REM 建议使用封装好的过程 :FTPXGet ,它会帮你调用 :GenerateFTPGetCommand 去启
- REM 动 :GenerateUnixFTPGetCommandCore ,确保其正确运行并且清理产生的临时文件,
- REM 但是你可以修改 Folder Operation 和 File Operation 的内容达到个性化的目的。
- REM ============================================================================
- :FTPXGet
- set $ftpp="%temp%\FTP_Paths.txt"
- set $ftpq="%temp%\CommandQueue.txt"
- if [%1]==[] (set /p $srv=FTP站点: ) else (set $srv=%1)
- if [%2]==[] (set /p $user=用户名: ) else (set $user=%2)
- if [%3]==[] (set /p $pwd=密码: ) else (set $pwd=%3)
- if [%4]==[] (set /p $rdir=远程目录:) else (set $rdir=%4)
- if [%5]==[] (set /p $ldir=本地目录:) else (set $ldir="%~f5")
- echo 远程路径:%$rdir%
- echo 本地路径:%$ldir:"=%
- call :GenerateFTPGetCommand %$srv% %$user% %$pwd% %$rdir% %$ldir% %$ftpp% %$ftpq%
- echo 启动FTP文件传输队列...
- ftp -v -s:%$ftpq%
- echo 文件传输完成。
- del %$ftpp%,%$ftpq%
- goto :EOF
- REM 启动 :GenerateUnixFTPGetCommandCore 递归过程并且负责清理其产生的临时文件,
- REM FTP服务器=%1,用户名=%2,密码=%3,远程目录=%4,本地目录=%5
- REM 远程子目录列表=%6,保存FTP命令传输队列的文件=%7
- :GenerateFTPGetCommand
- if [%7]==[] (
- echo ERROR : 参数不足,已退出。
- goto :EOF
- )
- echo 初始化...
- set $_srv=%1
- set $_user=%2
- set $_pwd=%3
- REM 清除特定类型的缓存文件
- if exist "%temp%\*.$ftp_cmd" del /q "%temp%\*.$ftp_cmd"
- if exist "%temp%\*.$dir_rst" del /q "%temp%\*.$dir_rst"
- if exist "%temp%\*.$dir_gen" del /q "%temp%\*.$dir_gen"
- if exist %6 del /f /q %6
- REM 登录到服务器执行一次 dir 命令,根据输出文本判断目录列表类型.
- REM 注意:通过 PASV 命令只能识别服务器类型,而目录列表类型是可以人为更改的。
- echo 正在分析服务器类型...
- (echo open %$_srv%
- echo %$_user%
- echo %$_pwd%
- echo prompt
- echo verbose
- echo binary
- echo dir / "%temp%\$roo$.$dir_rst"
- echo bye)>"%temp%\ftpcmd.$ftp_cmd"
- ftp -s:"%temp%\ftpcmd.$ftp_cmd">nul
- REM MS-DOS格式列表以日期开头,第一个字符为数字,UNIX格式以属性开头,不含数字。
- REM 根据此特征可以查看第一个字符进行判断服务器采取的是哪一种列表格式。
- findstr "^[0-9]" "%temp%\$roo$.$dir_rst" 1>nul 2>&1
- set $_typeUnixOrMSDOS=%errorlevel%
- set /p $=目录列表样式:<nul
- if %$_typeUnixOrMSDOS% equ 0 (echo MS-DOS) else (echo Unix)
- REM 创建文件传输队列的FTP命令行文件并写入开头
- echo 正在映射文件夹并添加FTP传输队列...
- (echo open %$_srv%
- echo %$_user%
- echo %$_pwd%
- echo binary)>%7
- REM 清空两个影响判断的关键变量
- set "BASE_FOLDER="
- set "LEN_SKIP="
- REM 已经做好了准备工作,启动过程
- call :GenerateUnixFTPGetCommandCore %$_typeUnixOrMSDOS% %$_srv% %$_user% %$_pwd% %4 %5 %6 %7
- REM 写入结束命令
- echo bye>>%7
- REM 清除临时文件
- echo 正在清除临时文件...
- del /q %temp%\*.$ftp_cmd,%temp%\*.$dir_rst,%temp%\*.$dir_gen
- goto :EOF
- REM 以用户名 %3 密码 %4 登录目录列表类型为 %1 的 FTP 服务器 %2 ,
- REM 获取其目录 %5 下的子文件夹路径以及文件路径,准备下载为本地目录 %6 ,
- REM 文件夹列表追加到文件 %7 中,FTP命令序列追加到 %8 中。
- REM 执行过程中在 %temp% 中产生后缀为 .$ftp_cmd .$dir_rst .$dir_gen 的临时文件。
- REM 注意:远程 FTP 服务器目录列表输出样式必须为 UNIX 样式。
- :GenerateUnixFTPGetCommandCore
- setlocal enabledelayedexpansion
- if [%8]==[] (
- echo ERROR : 参数不足,已退出。
- goto :EOF
- )
- set $__srv=%2
- set $__user=%3
- set $__pwd=%4
- REM 去掉远程路径中的双引号以及重复的斜杠
- set $__rcp=%5/
- set $__rcp=!$__rcp:\=/!
- set $__rcp=!$__rcp:"=!
- set $__rcp=!$__rcp://=/!
- REM 此路径下执行 FTP 命令 dir 的结果保存到的临时文件
- set $__cl=!$__rcp:/=$!
- REM 远程目录文件夹列表
- set $__rst=%7
- REM 保存最终要生成的 FTP 命令队列的文件
- set $__cq=%8
- REM 因为可能是重复使用,故不采取 defined 来判断 BASE_FOLDER 和 LEN_SKIP
- if "!BASE_FOLDER!"=="" set BASE_FOLDER=!$__rcp!
- REM 得到基础路径的长度,以便之后只截取相对路径
- if "!LEN_SKIP!"=="" (
- set /a LEN_SKIP=0
- for /l %%i in (0,1,1000) do (
- if not "!BASE_FOLDER:~%%i,1!"=="" (
- set /a LEN_SKIP+=1
- )
- )
- )
- REM 去掉本地路径中的双引号以及重复的斜杠
- set $__lcp=%6\!$__rcp:~%LEN_SKIP%!
- set $__lcp=!$__lcp:/=\!
- set $__lcp=!$__lcp:"=!
- set $__lcp=!$__lcp:\\=\!
- REM 追加一条路径信息到结果
- echo !$__rcp! --^> !$__lcp!
- echo !$__rcp!>>!$__rst!
- REM ============= Folder Operation ====== Start =================
- if not exist "!$__lcp!" md "!$__lcp!">>!$__cq!
- echo lcd "!$__lcp:~0,-1!">>!$__cq!
- REM ============= Folder Operation ====== End =================
- REM 生成获取当前远程目录下文件列表的 FTP 命令行并执行
- (echo open !$__srv!
- echo !$__user!
- echo !$__pwd!
- echo prompt
- echo verbose
- echo binary
- REM 如果目录列表格式是 MS-DOS 格式,则切换为 UNIX 以便统一处理
- if %1 equ 0 echo quote site dirstyle
- echo dir "!$__rcp!" "%temp%\!$__cl!.$dir_rst"
- echo bye)>"%temp%\ftpcmd.$ftp_cmd"
- ftp -s:"%temp%\ftpcmd.$ftp_cmd" 1>nul
- REM 属性第一位是字符 d 的是文件夹,查找不是 d 开头的行,得到所有文件名,生成命令
- for /f "tokens=1,2,3,4,5,6,7,8,* delims= " %%a in ('type "%temp%\!$__cl!.$dir_rst"^|findstr "^^[^^d]"') do (
- REM ============= File Operation ====== Start =================
- if not "%%i"=="" echo get "!$__rcp!%%i">>!$__cq!
- REM ============= File Operation ====== End =================
- )
- REM 如果找到 d 开头的行,说明此目录还有子目录
- type "%temp%\!$__cl!.$dir_rst"|findstr "^d" 1>nul
- if !errorlevel!==0 (
- REM 将子目录路径存放到临时文件
- for /f "tokens=1,2,3,4,5,6,7,8,* delims= " %%a in ('type "%temp%\!$__cl!.$dir_rst"^|findstr "^^d"') do (
- REM 去掉父目录(..),当前目录(.),否则会死循环
- if not "%%i"=="" if not "%%i"=="." if not "%%i"==".." echo !$__rcp!/%%i>>"%temp%\!$__cl!.$dir_gen"
- )
- REM 对所有子目录调用自身,遍历所有文件夹
- if exist "%temp%\!$__cl!.$dir_gen" for /f "usebackq delims=" %%a in ("%temp%\!$__cl!.$dir_gen") do (
- call :GenerateUnixFTPGetCommandCore %1 !$__srv! !$__user! !$__pwd! "%%a" %6 !$__rst! !$__cq!
- )
- )
- endlocal
- goto :EOF
复制代码
作者: Batcher 时间: 2011-9-21 22:26
回复 2# HMB0002
可以参考一下这个思路:批处理实现FTP整站上传
http://bbs.bathome.net/thread-12525-1-1.html
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |