上一篇讲过如何利用winscp脚本同步本地或远程的文件,但实际使用过程中遇到一个问题,
Winscp只能同步指定目录下所有文件(包括子目录),可以通过VBS动态生成脚本文件,但也只能同步一个指定目录所有文件.如果想要同步目录中的个别文件,比如说同步所有目录中修改日期为某一天的文件或者特定名称的文件时,利用winscp脚本就没有办法解决这个问题,这时就需要我们去写程序解决该问题了.我觉得还是自己去写一个FTP组件才能满足特定的要求.
一, 我先讲一下如何利用VBS动态生成脚本文件
遇到问题: 如果脚本中指定的远程目录不存在,程序会自动将根目录下的所有文件都同步过来.
<Root>
<PubDate></PubDate>
<Companys>
<Company>
<Name>alcatel</Name>
<FTPConnection>ftp://user1:password1@ftp.test.com:21</FTPConnection>
<LocalDirectory>E:\test\Postion\XmlFile_Source\34091</LocalDirectory>
<RemoteDirectory>/Position</RemoteDirectory>
<SynchronizeWay>local</SynchronizeWay>
<NeedDate>false</NeedDate>
<DateStyle>yyyy-mm-dd</DateStyle>
</Company>
<Company>
<Name>Fosun</Name>
<FTPConnection>ftp://user2:password2@ftp.test.com:21</FTPConnection>
<LocalDirectory>E:\test\Postion\XmlFile_Source\384821</LocalDirectory>
<RemoteDirectory>/Position</RemoteDirectory>
<SynchronizeWay>local</SynchronizeWay>
<NeedDate>false</NeedDate>
<DateStyle>yyyy-mm-dd</DateStyle>
</Company>
</Companys>
</Root>
脚本模板文件
# winscp.exe /console /script=sample.txt
# Automatically answer all prompts negatively not to stall
# the script on errors
# option echo on|off
option echo off
# option batch on|off|abort|continue
option batch on
# option confirm on|off
option confirm off
# option transfer binary|ascii|automatic
# option synchdelete on|off
# option exclude clear | <mask>[;<mask2>...]
# option include clear | <mask>[;<mask2>...]
# open [ sftp|ftp|scp:// ][ <user> [ :password ] @ ] <host> [ :<port> ]
# open user:password@example.com
# Connect
open [%%FTPConnection%%]
# Change remote directory
# cd /home/user
cd [%%RemoteDirectory%%]
# Change local directory
# set to Degussa's working dir
lcd [%%LocalDirectory%%]
# Force binary mode transfer
option transfer binary
# Download file to the local directory d:\
# get examplefile.txt d:\
# option synchdelete on|off
option synchdelete off
# option include clear | <mask>[;<mask2>...]
# option include /2008-*-*/;/2009-*-*/;/2010-*-*/;/2011-*-*/;/2012-*-*/;/2013-*-*/
# synchronize local|remote|both [ <local directory> [ <remote directory> ] ]
synchronize [%%Way%%]
# Disconnect
close
# Exit WinSCP
exit
download.vbs
Option Explicit
Dim PubDate '处理某一天数据
Dim CompanyList '多个公司配置列表
Dim shell, strRootPath, strCommand
Dim strCfgFilePath, DataFolder, LogFolder
Set shell = CreateObject("Wscript.Shell")
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
'当前程序运行目录
strRootPath = Left(Wscript.scriptFullName, InstrRev(Wscript.scriptFullName, "\"))
'WINSCP脚本文件目录
DataFolder = strRootPath & "Data"
If Not objFSO.FolderExists(DataFolder) Then
objFSO.CreateFolder(DataFolder)
End If
'日志目录
LogFolder = strRootPath & "Log"
If Not objFSO.FolderExists(LogFolder) Then
objFSO.CreateFolder(LogFolder)
End If
'配置文件路径
strCfgFilePath = strRootPath & "syscfg.xml"
'读取配置文件
If Not ReadCfg(strCfgFilePath) Then
mLog "配置文件出错,请检查!"
End If
Dim intX
Dim strFile
For intX = 0 To UBound(CompanyList)-1
If Len(CompanyList(intX,1)) > 0 Then
strFile = UpdateWinscpScript(CompanyList(intX,0), CompanyList(intX,1), CompanyList(intX,2), CompanyList(intX,3), CompanyList(intX,4))
If Len(strFile) <> 0 Then
mLog "Shell.run(winscp /console /script=" & strFile & ")"
Shell.run("winscp /console /script=" & strFile)
End If
Else
Exit For
End If
Next
'生成Winscp脚本文件
Function UpdateWinscpScript(name, ftp, localDir, remoteDir, syschronizeWay)
Dim strFilePath, strTemplatePath
strFilePath = DataFolder & "/" & name & ".txt"
strTemplatePath = strRootPath & "template.txt"
If Not objFSO.FileExists(strTemplatePath) Then
mLog "脚本模板文件不存在!(" & strTemplatePath & ")"
UpdateWinscpScript = ""
Exit Function
End If
'如果文件存在,先删除文件
If objFSO.FileExists(strFilePath) Then
objFSO.DeleteFile(strFilePath)
End If
'读取模板文件
Dim strAllText
Dim file
On Error Resume Next
Set file = objFSO.OpenTextFile(strTemplatePath)
If Not file.AtEndOfStream Then
strAllText = file.ReadAll
End If
file.Close
If Err.Number <> 0 Then
mLog "[UpdateWinscpScript][ERROR]" & Err.Description
Err.Clear
End If
If Len(strAllText) = 0 Then
mLog "[UpdateWinscpScript][ERROR]模板文件无内容,请检查!"
UpdateWinscpScript = ""
Exit Function
End If
Set file = objFSO.CreateTextFile(strFilePath)
strAllText = Replace(strAllText, "[%%FTPConnection%%]", ftp)
strAllText = Replace(strAllText, "[%%RemoteDirectory%%]", remoteDir)
strAllText = Replace(strAllText, "[%%LocalDirectory%%]", localDir)
strAllText = Replace(strAllText, "[%%Way%%]", syschronizeWay)
file.write strAllText
file.close
If Err.Number <> 0 Then
mLog "[UpdateWinscpScript][ERROR]" & Err.Description
UpdateWinscpScript = ""
Exit Function
End If
UpdateWinscpScript = strFilePath
End Function
'读取配置文件
Function ReadCfg(cfgFilePath)
on Error resume next
Dim fso
set fso = CreateObject("Scripting.FileSystemObject")
'如果没有找到配置文件,退出Function
If Not fso.FileExists(cfgFilePath) Then
ReadCfg = false
Exit Function
End If
Dim XmlDoc
Dim rootNode
Set XmlDoc = CreateObject("Microsoft.XMLDOM")
If XmlDoc.load(cfgFilePath) Then
'加载文件成功
Set rootNode = XmlDoc.documentElement
PubDate = Trim(rootNode.selectSingleNode("PubDate").text)
If Len(PubDate) = 0 Then
PubDate = date
Else
PubDate = CDate(PubDate)
End If
If Err.Number <> 0 Then
mLog "[ReadCfg][ERROR]" & Err.Description
Err.Clear
End If
Dim i, j
i = 0
Dim strRemotePath, strLocalPath, company
Dim CompanyCount
CompanyCount = rootNode.selectNodes("Companys/Company").length
Redim CompanyList(CompanyCount, 7)
for each company in rootNode.selectNodes("Companys/Company")
strRemotePath = ""
mLog "***************************************************"
'Name
CompanyList(i,0) = company.selectSingleNode("Name").text
mLog "Name: " & CompanyList(i,0)
'FTPConnection
CompanyList(i,1) = company.selectSingleNode("FTPConnection").text
mLog "FTP: " & CompanyList(i,1)
'SynchronizeWay
CompanyList(i,4) = company.selectSingleNode("SynchronizeWay").text
mLog "SynchronizeWay: " & CompanyList(i,4)
'NeedDate
CompanyList(i,5) = company.selectSingleNode("NeedDate").text
mLog "NeedDate: " & CompanyList(i,5)
'DateStyle
CompanyList(i,6) = company.selectSingleNode("DateStyle").text
mLog "DateStyle: " & CompanyList(i,6)
'LocalDirectory
strLocalPath = Trim(company.selectSingleNode("LocalDirectory").text)
If Len(strLocalPath) > 0 Then
If Right(strLocalPath,1)="\" Then
strLocalPath = Left(strLocalPath,instrRev(strLocalPath,"\")-1)
End If
If CompanyList(i,5) Then
strLocalPath = GetPathWithDate(strLocalPath, PubDate, CompanyList(i,6), "\")
End If
If Not fso.FolderExists(strLocalPath) Then
CreateDirectory strLocalPath, "\"
End If
CompanyList(i,2) = strLocalPath
End If
mLog "Local Directory: " & CompanyList(i,2)
If Err.Number <> 0 Then
mLog "[ReadCfg][ERROR]" & Err.Description
Err.Clear
End If
'RemoteDirectory
strRemotePath = Trim(company.selectSingleNode("RemoteDirectory").text)
'去掉路径后面的/
If Right(strRemotePath,1)="/" Then
CompanyList(i,3) = Left(strRemotePath,instrRev(strRemotePath,"/")-1)
Else
CompanyList(i,3) = strRemotePath
End If
If CompanyList(i,5) Then
CompanyList(i,3) = GetPathWithDate(CompanyList(i,3), PubDate, CompanyList(i,6), "/")
End If
mLog "Remote Directory: " & CompanyList(i,3)
i = i + 1
Next
ReadCfg = True
Else
'加载文件失败
ReadCfg = False
End If
End Function
'返回带日期的远程目录
Function GetPathWithDate(strDir, strDate, strStyle, seperator)
On Error Resume Next
If len(year(strDate)) = 0 Then
strDate = Date
End If
select case Lcase(strStyle)
case "yyyy-mm-dd"
GetPathWithDate = strDir & seperator & year(strDate) & "-" & Right("0"&Month(strDate),2) & "-" & Right("0"&Day(strDate),2)
case "yyyy_mm_dd"
GetPathWithDate = strDir & seperator & year(strDate) & "_" & Right("0"&Month(strDate),2) & "_" & Right("0"&Day(strDate),2)
case "yyyymmdd"
GetPathWithDate = strDir & seperator & year(strDate) & Right("0"&Month(strDate),2) & Right("0"&Day(strDate),2)
case "yyyy-m-d"
GetPathWithDate = strDir & seperator & year(strDate) & "-" & Month(strDate) & "-" & Day(strDate)
Case "yyyy_m_d"
GetPathWithDate = strDir & seperator & year(strDate) & "_" & Month(strDate) & "_" & Day(strDate)
Case "yyyymd"
GetPathWithDate = strDir & seperator & year(strDate) & Month(strDate) & Day(strDate)
End Select
End Function
'创建本地目录
Sub CreateDirectory(dir, seperator)
On Error Resume Next
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim path
path = ""
Dim i
Dim arrDir
arrDir = split(dir, seperator)
for i = 0 to UBound(arrDir)
path = path & arrDir(i) & seperator
If Not fso.FolderExists(path) Then
fso.CreateFolder(path)
End If
If Err.Number <> 0 Then
mLog "[CreateDirectory][ERROR]" & Err.Description
Err.Clear
End If
Next
End Sub
' 记录日志
Private Function mLog(info)
Dim logFile, dt, yyyy, mm, dd
dt = Now
yyyy = Year(dt)
mm = Month(dt)
dd = Day(dt)
If Len(mm)=1 Then
mm = "0" & mm
End If
If Len(dd)=1 Then
dd = "0" & dd
End If
dt = yyyy & "-" & mm & "-" & dd & " " & Time()
Do
On Error Resume Next
Err.Clear
Set logfile = objFSO.OpenTextFile(LogFolder & "\" & yyyy & mm & dd & ".log", 8, True)
WScript.Sleep(10)
Loop Until not(Err.Number<>0)
logFile.WriteLine dt & "->" & info
logFile.Close()
WScript.Echo dt & "->" & info
End Function