[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[FTP] 普遍适用的FTP文件夹上传下载批处理函数

之前有说FTP的mput和mget命令能上传下载文件夹,但是不能对子文件夹进行操作,这里给出的两个函数 FTPXPut 和 FTPXGet 可以递归操作子文件夹里面的文件。
过程从会在临时文件夹生成一些文件,之后会自动删除。
注意:你可以修改指定部位的代码,达到更个性化的目的,因为他们已经精确到了对每个文件夹和文件的操作,具体位置详见注释。

下面是一个在批处理文件中调用它们的实例,两个下载的例子可以直接运行,因为是访问公共资源;上传的例子需要自己修改,如果你有某个FTP服务器的帐号。
ftpXgetXput_sample.bat 链接: https://pan.baidu.com/s/1iQ1AlKS1xsOiVhlqLnZVGA?pwd=qqdt
  1. @echo off
  2. REM 上传下载测试(匿名用户 anonymous 密码任意)
  3. REM 下载一个 UNIX 目录列表类型服务器上的文件夹
  4. echo ***************** 开始从 UNIX 服务器下载文件夹 **************************
  5. set rp=/pub/mirrors/ubuntu/pool/main/l/language-pack-zh/
  6. call :FTPXGet ftp.cs.stanford.edu anonymous Spring  %rp% .\zh
  7. pause
  8. REM 下载一个 MS-DOS 目录列表类型服务器上的文件夹
  9. echo ***************** 开始从 WINDOWS 服务器下载文件夹 ***********************
  10. set rp=/Products/Windows/Windows95/CDRomExtras/AdministrationTools/
  11. call :FTPXGet ftp.microsoft.com   anonymous Brother %rp% D:\ms
  12. pause
  13. echo ***************** 开始上传文件夹到远程 FTP 服务器 ***********************
  14. call :FTPXPut 10.120.6.43 was1 admin "%userprofile%\Favorites" /MyFavoriteSites
  15. pause
  16. goto :EOF
  17. REM 上传一个本地文件夹到 FTP 服务器
  18. REM ============================================================================
  19. REM [FTPXPut]   (C)2011  Spring
  20. REM 将一个本地文件夹 %4 上传为 FTP 服务器 %1 的 %5 文件夹,用户名 %2,密码 %3。
  21. REM 你可以修改 Folder Operation 和 File Operation 的内容达到个性化的目的。
  22. REM ============================================================================
  23. :FTPXPut
  24. if [%5]==[] (
  25.     echo ERROR : 参数不足,已退出。
  26.     goto :EOF
  27. )
  28. setlocal enabledelayedexpansion
  29. REM 存放 FTP 命令行的临时文件
  30. set $__ftpq="%temp%\CommandQueue%random%.txt"
  31. REM 本地文件夹绝对路径,以 "\" 结尾
  32. set $__ldir=%~f4\
  33. set $__ldir=!$__ldir:\\=\!
  34. REM 远程文件夹绝对路径,以 "/" 结尾
  35. set $__rdir=/%5/
  36. set $__rdir=!$__rdir:\=/!
  37. set $__rdir=!$__rdir:"=!
  38. set $__rdir=!$__rdir://=/!
  39. REM 检测基本条件
  40. echo 本地目录:!$__ldir!
  41. echo 远程目录:!$__rdir!
  42. echo 初始化...
  43. if not exist "!$__ldir!" (
  44.     echo ERROR : 找不到文件夹 "!$__ldir!",已退出。
  45.     goto :EOF
  46. )
  47. REM 本地文件夹顶层目录的长度,在获取相对路径时会用到
  48. set /a LEN_SKIP=0
  49. for /l %%i in (0,1,1000) do (
  50.     if not "!$__ldir:~%%i,1!"=="" (
  51.         set /a LEN_SKIP+=1
  52.     )
  53. )
  54. REM 创建 FTP 命令行文件并写入登录命令和建立目标顶层文件夹的命令
  55. (echo open %1
  56. echo %2
  57. echo %3
  58. echo binary)>!$__ftpq!
  59. echo 正在映射文件夹并添加FTP传输队列...
  60. REM 先进行文件夹及子文件夹查询
  61. for /f "delims=" %%a in ('echo !$__ldir!^&dir /s /b /ad "!$__ldir!"') do (
  62.     REM 当前本地路径
  63.     set "$__lcp=%%a\"
  64.     set "$__lcp=!$__lcp:\\=\!"
  65.     REM 相对路径   
  66.     set "$__lcrp=!$__lcp:~%LEN_SKIP%!"
  67.     REM 最顶层的文件夹路径全被截掉了,因此加个判断避免出错
  68.     if not "!$__lcrp!"=="" set "$__lcrp=!$__lcrp:\=/!"
  69.     echo !$__lcp!  --^>  !$__rdir!!$__lcrp!
  70.     REM 添加建立远程文件夹并将远程目录切换至此文件夹的命令
  71.     REM ==================== Folder Operation ====== Start =====================
  72.     echo mkdir "!$__rdir!!$__lcrp!">>!$__ftpq!
  73.     echo cd "!$__rdir!!$__lcrp!">>!$__ftpq!
  74.     REM ==================== Folder Operation ======  End  =====================
  75.     REM 对每个子文件夹进行文件查询并生成操作命令
  76.     for /f "delims=" %%z in ('dir /b /a-d "!$__lcp!" 2^>nul') do (
  77.         REM ================= File Operation ====== Start ======================
  78.         echo put "!$__lcp!%%z">>!$__ftpq!
  79.         REM ================= File Operation ======  End  ======================
  80.     )
  81. )
  82. REM 写入退出 FTP 的命令
  83. echo bye>>!$__ftpq!
  84. REM 启动传输过程
  85. echo 启动FTP文件传输队列...
  86. ftp -v -s:!$__ftpq!
  87. echo 文件传输完成。
  88. REM 清除过程中产生的临时文件
  89. echo 正在清除临时文件...
  90. del !$__ftpq!
  91. echo 操作完成。
  92. endlocal
  93. goto :EOF
  94. REM 下载一个 FTP 文件夹到本地
  95. REM ============================================================================
  96. REM  [FTPXGet]   (C)2011  Spring
  97. REM  建议使用封装好的过程 :FTPXGet ,它会帮你调用 :GenerateFTPGetCommand 去启
  98. REM  动 :GenerateUnixFTPGetCommandCore ,确保其正确运行并且清理产生的临时文件,
  99. REM  但是你可以修改 Folder Operation 和 File Operation 的内容达到个性化的目的。
  100. REM ============================================================================
  101. :FTPXGet
  102. set $ftpp="%temp%\FTP_Paths.txt"
  103. set $ftpq="%temp%\CommandQueue.txt"
  104. if [%1]==[] (set /p  $srv=FTP站点: ) else (set  $srv=%1)
  105. if [%2]==[] (set /p $user=用户名:  ) else (set $user=%2)
  106. if [%3]==[] (set /p  $pwd=密码:    ) else (set  $pwd=%3)
  107. if [%4]==[] (set /p $rdir=远程目录:) else (set $rdir=%4)
  108. if [%5]==[] (set /p $ldir=本地目录:) else (set $ldir="%~f5")
  109. echo 远程路径:%$rdir%
  110. echo 本地路径:%$ldir:"=%
  111. call :GenerateFTPGetCommand %$srv% %$user% %$pwd% %$rdir% %$ldir% %$ftpp% %$ftpq%
  112. echo 启动FTP文件传输队列...
  113. ftp -v -s:%$ftpq%
  114. echo 文件传输完成。
  115. del %$ftpp%,%$ftpq%
  116. goto :EOF
  117. REM 启动 :GenerateUnixFTPGetCommandCore 递归过程并且负责清理其产生的临时文件,
  118. REM FTP服务器=%1,用户名=%2,密码=%3,远程目录=%4,本地目录=%5
  119. REM 远程子目录列表=%6,保存FTP命令传输队列的文件=%7
  120. :GenerateFTPGetCommand
  121. if [%7]==[] (
  122.     echo ERROR : 参数不足,已退出。
  123.     goto :EOF
  124. )
  125. echo 初始化...
  126. set $_srv=%1
  127. set $_user=%2
  128. set $_pwd=%3
  129. REM 清除特定类型的缓存文件
  130. if exist "%temp%\*.$ftp_cmd" del /q "%temp%\*.$ftp_cmd"
  131. if exist "%temp%\*.$dir_rst" del /q "%temp%\*.$dir_rst"
  132. if exist "%temp%\*.$dir_gen" del /q "%temp%\*.$dir_gen"
  133. if exist %6 del /f /q %6
  134. REM 登录到服务器执行一次 dir 命令,根据输出文本判断目录列表类型.
  135. REM 注意:通过 PASV 命令只能识别服务器类型,而目录列表类型是可以人为更改的。
  136. echo 正在分析服务器类型...
  137. (echo open %$_srv%
  138. echo %$_user%
  139. echo %$_pwd%
  140. echo prompt
  141. echo verbose
  142. echo binary
  143. echo dir / "%temp%\$roo$.$dir_rst"
  144. echo bye)>"%temp%\ftpcmd.$ftp_cmd"
  145. ftp -s:"%temp%\ftpcmd.$ftp_cmd">nul
  146. REM MS-DOS格式列表以日期开头,第一个字符为数字,UNIX格式以属性开头,不含数字。
  147. REM 根据此特征可以查看第一个字符进行判断服务器采取的是哪一种列表格式。
  148. findstr "^[0-9]" "%temp%\$roo$.$dir_rst" 1>nul 2>&1
  149. set $_typeUnixOrMSDOS=%errorlevel%
  150. set /p $=目录列表样式:<nul
  151. if %$_typeUnixOrMSDOS% equ 0 (echo MS-DOS) else (echo Unix)
  152. REM 创建文件传输队列的FTP命令行文件并写入开头
  153. echo 正在映射文件夹并添加FTP传输队列...
  154. (echo open %$_srv%
  155. echo %$_user%
  156. echo %$_pwd%
  157. echo binary)>%7
  158. REM 清空两个影响判断的关键变量
  159. set "BASE_FOLDER="
  160. set "LEN_SKIP="
  161. REM 已经做好了准备工作,启动过程
  162. call :GenerateUnixFTPGetCommandCore %$_typeUnixOrMSDOS% %$_srv% %$_user% %$_pwd% %4 %5 %6 %7
  163. REM 写入结束命令
  164. echo bye>>%7
  165. REM 清除临时文件
  166. echo 正在清除临时文件...
  167. del /q %temp%\*.$ftp_cmd,%temp%\*.$dir_rst,%temp%\*.$dir_gen
  168. goto :EOF
  169. REM 以用户名 %3 密码 %4 登录目录列表类型为 %1 的 FTP 服务器 %2 ,
  170. REM 获取其目录 %5 下的子文件夹路径以及文件路径,准备下载为本地目录 %6 ,
  171. REM 文件夹列表追加到文件 %7 中,FTP命令序列追加到 %8 中。
  172. REM 执行过程中在 %temp% 中产生后缀为 .$ftp_cmd .$dir_rst .$dir_gen 的临时文件。
  173. REM     注意:远程 FTP 服务器目录列表输出样式必须为 UNIX 样式。
  174. :GenerateUnixFTPGetCommandCore
  175. setlocal enabledelayedexpansion
  176. if [%8]==[] (
  177.     echo ERROR : 参数不足,已退出。
  178.     goto :EOF
  179. )
  180. set $__srv=%2
  181. set $__user=%3
  182. set $__pwd=%4
  183. REM 去掉远程路径中的双引号以及重复的斜杠
  184. set $__rcp=%5/
  185. set $__rcp=!$__rcp:\=/!
  186. set $__rcp=!$__rcp:"=!
  187. set $__rcp=!$__rcp://=/!
  188. REM 此路径下执行 FTP 命令 dir 的结果保存到的临时文件
  189. set $__cl=!$__rcp:/=$!
  190. REM 远程目录文件夹列表
  191. set $__rst=%7
  192. REM 保存最终要生成的 FTP 命令队列的文件
  193. set $__cq=%8
  194. REM 因为可能是重复使用,故不采取 defined 来判断 BASE_FOLDER 和 LEN_SKIP
  195. if "!BASE_FOLDER!"=="" set BASE_FOLDER=!$__rcp!
  196. REM 得到基础路径的长度,以便之后只截取相对路径
  197. if "!LEN_SKIP!"=="" (
  198.     set /a LEN_SKIP=0
  199.     for /l %%i in (0,1,1000) do (
  200.         if not "!BASE_FOLDER:~%%i,1!"=="" (
  201.             set /a LEN_SKIP+=1
  202.         )
  203.     )
  204. )
  205. REM 去掉本地路径中的双引号以及重复的斜杠
  206. set $__lcp=%6\!$__rcp:~%LEN_SKIP%!
  207. set $__lcp=!$__lcp:/=\!
  208. set $__lcp=!$__lcp:"=!
  209. set $__lcp=!$__lcp:\\=\!
  210. REM 追加一条路径信息到结果
  211. echo !$__rcp!  --^>  !$__lcp!
  212. echo !$__rcp!>>!$__rst!
  213. REM ============= Folder Operation ====== Start =================
  214. if not exist "!$__lcp!" md "!$__lcp!">>!$__cq!
  215. echo lcd "!$__lcp:~0,-1!">>!$__cq!
  216. REM ============= Folder Operation ======  End  =================
  217. REM 生成获取当前远程目录下文件列表的 FTP 命令行并执行
  218. (echo open !$__srv!
  219. echo !$__user!
  220. echo !$__pwd!
  221. echo prompt
  222. echo verbose
  223. echo binary
  224. REM 如果目录列表格式是 MS-DOS 格式,则切换为 UNIX 以便统一处理
  225. if %1 equ 0 echo quote site dirstyle
  226. echo dir "!$__rcp!" "%temp%\!$__cl!.$dir_rst"
  227. echo bye)>"%temp%\ftpcmd.$ftp_cmd"
  228. ftp -s:"%temp%\ftpcmd.$ftp_cmd" 1>nul
  229. REM 属性第一位是字符 d 的是文件夹,查找不是 d 开头的行,得到所有文件名,生成命令
  230. for /f "tokens=1,2,3,4,5,6,7,8,* delims= " %%a in ('type "%temp%\!$__cl!.$dir_rst"^|findstr "^^[^^d]"') do (
  231.     REM ============= File Operation ====== Start =================
  232.     if not "%%i"=="" echo get "!$__rcp!%%i">>!$__cq!
  233.     REM ============= File Operation ======  End  =================
  234. )
  235. REM 如果找到 d 开头的行,说明此目录还有子目录
  236. type "%temp%\!$__cl!.$dir_rst"|findstr "^d" 1>nul
  237. if !errorlevel!==0 (
  238.     REM 将子目录路径存放到临时文件
  239.     for /f "tokens=1,2,3,4,5,6,7,8,* delims= " %%a in ('type "%temp%\!$__cl!.$dir_rst"^|findstr "^^d"') do (
  240.         REM 去掉父目录(..),当前目录(.),否则会死循环
  241.         if not "%%i"=="" if not "%%i"=="." if not "%%i"==".." echo !$__rcp!/%%i>>"%temp%\!$__cl!.$dir_gen"
  242.     )
  243.     REM 对所有子目录调用自身,遍历所有文件夹
  244.     if exist "%temp%\!$__cl!.$dir_gen" for /f "usebackq delims=" %%a in ("%temp%\!$__cl!.$dir_gen") do (
  245.         call :GenerateUnixFTPGetCommandCore %1 !$__srv! !$__user! !$__pwd! "%%a" %6 !$__rst! !$__cq!
  246.     )
  247. )
  248. endlocal
  249. goto :EOF
复制代码

回复 2# HMB0002


可以参考一下这个思路:批处理实现FTP整站上传
http://bbs.bathome.net/thread-12525-1-1.html
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

返回列表