如何脚本FTP上传和下载?

我试图做一个batch file上传到FTP服务器的文件。 如果我手动键入它工作正常,但是当我运行batch file它连接后它停止…它说

connected to domain.com. 220 microsoft ftp server User(domain.com:(none)): 

那么没有别的。 这到底是怎么回事?

以下是我的batch file:

 ftp www.domainhere.com user useridhere passwordhere put test.txt bye pause 

按照原来的海报想象的方式来编写一个FTP会话是一个合理的想法,这是Expect会帮助的。 Windows上的batch file不能这样做。

但是,而不是做cURL或期望,你可能会发现脚本与Powershell的FTP交互更容易。 这是一种不同的模式,因为您不是直接编写脚本来发送到FTP服务器。 相反,您将使用Powershell来操作为您生成FTP对话的对象。

上传:

 $File = "D:\Dev\somefilename.zip" $ftp = "ftp://username:password@example.com/pub/incoming/somefilename.zip" "ftp url: $ftp" $webclient = New-Object System.Net.WebClient $uri = New-Object System.Uri($ftp) "Uploading $File..." $webclient.UploadFile($uri, $File) 

下载:

 $File = "c:\store\somefilename.zip" $ftp = "ftp://username:password@example.com/pub/outbound/somefilename.zip" "ftp url: $ftp" $webclient = New-Object System.Net.WebClient $uri = New-Object System.Uri($ftp) "Downloading $File..." $webclient.DownloadFile($uri, $File) 

你需要Powershell来做到这一点。 如果你不知道,Powershell是像cmd.exe这样的shell,它运行你的.bat文件。 但是Powershell运行.ps1文件,而且function更强大。 Powershell是一个免费的Windows附件,将内置于未来版本的Windows中。 在这里得到它 。

资料来源: http : //poshcode.org/1134

用你的命令创build一个命令文件

即:commands.txt

 open www.domainhere.com user useridhere passwordhere put test.txt bye 

然后从命令行运行FTP客户端:ftp -s:commands.txt

注意:这将适用于Windows FTP客户端。

编辑:在密码之前的用户名之后应该有一个换行符。

batch file不这样工作。 他们不只是“input”一切 – 他们运行系统命令,在这种情况下, ftp ,等待他们返回,并运行下一个命令…所以在这种情况下,解释器只是等待ftp退出。

如果您必须使用ftp命令,则准备一个脚本文件(例如commands.txt并运行ftp -s:commands.txt

但是使用cURL或PHP / Perl / Python /脚本可能是一个更好的主意。

我已经用PowerShell完成了这个工作 :

 function DownloadFromFtp($destination, $ftp_uri, $user, $pass){ $dirs = GetDirecoryTree $ftp_uri $user $pass foreach($dir in $dirs){ $path = [io.path]::Combine($destination,$dir) if ((Test-Path $path) -eq $false) { "Creating $path ..." New-Item -Path $path -ItemType Directory | Out-Null }else{ "Exists $path ..." } } $files = GetFilesTree $ftp_uri $user $pass foreach($file in $files){ $source = [io.path]::Combine($ftp_uri,$file) $dest = [io.path]::Combine($destination,$file) "Downloading $source ..." Get-FTPFile $source $dest $user $pass } } function UploadToFtp($artifacts, $ftp_uri, $user, $pass){ $webclient = New-Object System.Net.WebClient $webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass) foreach($item in Get-ChildItem -recurse $artifacts){ $relpath = [system.io.path]::GetFullPath($item.FullName).SubString([system.io.path]::GetFullPath($artifacts).Length + 1) if ($item.Attributes -eq "Directory"){ try{ Write-Host Creating $item.Name $makeDirectory = [System.Net.WebRequest]::Create($ftp_uri+$relpath); $makeDirectory.Credentials = New-Object System.Net.NetworkCredential($user,$pass) $makeDirectory.Method = [System.Net.WebRequestMethods+FTP]::MakeDirectory; $makeDirectory.GetResponse(); }catch [Net.WebException] { Write-Host $item.Name probably exists ... } continue; } "Uploading $item..." $uri = New-Object System.Uri($ftp_uri+$relpath) $webclient.UploadFile($uri, $item.FullName) } } function Get-FTPFile ($Source,$Target,$UserName,$Password) { $ftprequest = [System.Net.FtpWebRequest]::create($Source) $ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password) $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile $ftprequest.UseBinary = $true $ftprequest.KeepAlive = $false $ftpresponse = $ftprequest.GetResponse() $responsestream = $ftpresponse.GetResponseStream() $targetfile = New-Object IO.FileStream ($Target,[IO.FileMode]::Create) [byte[]]$readbuffer = New-Object byte[] 1024 do{ $readlength = $responsestream.Read($readbuffer,0,1024) $targetfile.Write($readbuffer,0,$readlength) } while ($readlength -ne 0) $targetfile.close() } #task ListFiles { # # $files = GetFilesTree 'ftp://127.0.0.1/' "web" "web" # $files | ForEach-Object {Write-Host $_ -foregroundcolor cyan} #} function GetDirecoryTree($ftp, $user, $pass){ $creds = New-Object System.Net.NetworkCredential($user,$pass) $files = New-Object "system.collections.generic.list[string]" $folders = New-Object "system.collections.generic.queue[string]" $folders.Enqueue($ftp) while($folders.Count -gt 0){ $fld = $folders.Dequeue() $newFiles = GetAllFiles $creds $fld $dirs = GetDirectories $creds $fld foreach ($line in $dirs){ $dir = @($newFiles | Where { $line.EndsWith($_) })[0] [void]$newFiles.Remove($dir) $folders.Enqueue($fld + $dir + "/") [void]$files.Add($fld.Replace($ftp, "") + $dir + "/") } } return ,$files } function GetFilesTree($ftp, $user, $pass){ $creds = New-Object System.Net.NetworkCredential($user,$pass) $files = New-Object "system.collections.generic.list[string]" $folders = New-Object "system.collections.generic.queue[string]" $folders.Enqueue($ftp) while($folders.Count -gt 0){ $fld = $folders.Dequeue() $newFiles = GetAllFiles $creds $fld $dirs = GetDirectories $creds $fld foreach ($line in $dirs){ $dir = @($newFiles | Where { $line.EndsWith($_) })[0] [void]$newFiles.Remove($dir) $folders.Enqueue($fld + $dir + "/") } $newFiles | ForEach-Object { $files.Add($fld.Replace($ftp, "") + $_) } } return ,$files } function GetDirectories($creds, $fld){ $dirs = New-Object "system.collections.generic.list[string]" $operation = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails $reader = GetStream $creds $fld $operation while (($line = $reader.ReadLine()) -ne $null) { if ($line.Trim().ToLower().StartsWith("d") -or $line.Contains(" <DIR> ")) { [void]$dirs.Add($line) } } $reader.Dispose(); return ,$dirs } function GetAllFiles($creds, $fld){ $newFiles = New-Object "system.collections.generic.list[string]" $operation = [System.Net.WebRequestMethods+Ftp]::ListDirectory $reader = GetStream $creds $fld $operation while (($line = $reader.ReadLine()) -ne $null) { [void]$newFiles.Add($line.Trim()) } $reader.Dispose(); return ,$newFiles } function GetStream($creds, $url, $meth){ $ftp = [System.Net.WebRequest]::Create($url) $ftp.Credentials = $creds $ftp.Method = $meth $response = $ftp.GetResponse() return New-Object IO.StreamReader $response.GetResponseStream() } Export-ModuleMember UploadToFtp, DownLoadFromFtp 

我知道这是一个古老的问题,但我想在这里添加一些答案,希望帮助别人。

您可以使用-s:filename选项编写ftp命令。 语法只是传递给ftp shell的命令列表,每个命令都以换行符结尾。 这个页面有一个很好的参考可以用ftp执行的命令。

上传/下载整个目录结构

当您需要将整个目录树复制到FTP站点或从FTP站点复制时,使用正常的ftp不能很好地工作。 所以你可以使用类似的东西来处理这些情况。

这些脚本与Windows ftp命令一起使用,并允许从一个命令上传和下载整个目录。 这使得它在不同的系统上使用时非常自信。

基本上他们所做的是映射出要上传/下载的目录结构,将相应的ftp命令转储到文件中,然后在映射完成后执行这些命令。

ftpupload.bat

 @echo off SET FTPADDRESS=%1 SET FTPUSERNAME=%2 SET FTPPASSWORD=%3 SET LOCALDIR=%~f4 SET REMOTEDIR=%5 if "%FTPADDRESS%" == "" goto FTP_UPLOAD_USAGE if "%FTPUSERNAME%" == "" goto FTP_UPLOAD_USAGE if "%FTPPASSWORD%" == "" goto FTP_UPLOAD_USAGE if "%LOCALDIR%" == "" goto FTP_UPLOAD_USAGE if "%REMOTEDIR%" == "" goto FTP_UPLOAD_USAGE :TEMP_NAME set TMPFILE=%TMP%\%RANDOM%_ftpupload.tmp if exist "%TMPFILE%" goto TEMP_NAME SET INITIALDIR=%CD% echo user %FTPUSERNAME% %FTPPASSWORD% > %TMPFILE% echo bin >> %TMPFILE% echo lcd %LOCALDIR% >> %TMPFILE% cd %LOCALDIR% setlocal EnableDelayedExpansion echo mkdir !REMOTEDIR! >> !TMPFILE! echo cd %REMOTEDIR% >> !TMPFILE! echo mput * >> !TMPFILE! for /d /r %%d in (*) do ( set CURRENT_DIRECTORY=%%d set RELATIVE_DIRECTORY=!CURRENT_DIRECTORY:%LOCALDIR%=! echo mkdir "!REMOTEDIR!/!RELATIVE_DIRECTORY:~1!" >> !TMPFILE! echo cd "!REMOTEDIR!/!RELATIVE_DIRECTORY:~1!" >> !TMPFILE! echo mput "!RELATIVE_DIRECTORY:~1!\*" >> !TMPFILE! ) echo quit >> !TMPFILE! endlocal EnableDelayedExpansion ftp -n -i "-s:%TMPFILE%" %FTPADDRESS% del %TMPFILE% cd %INITIALDIR% goto FTP_UPLOAD_EXIT :FTP_UPLOAD_USAGE echo Usage: ftpupload [address] [username] [password] [local directory] [remote directory] echo. :FTP_UPLOAD_EXIT set INITIALDIR= set FTPADDRESS= set FTPUSERNAME= set FTPPASSWORD= set LOCALDIR= set REMOTEDIR= set TMPFILE= set CURRENT_DIRECTORY= set RELATIVE_DIRECTORY= @echo on 

ftpget.bat

 @echo off SET FTPADDRESS=%1 SET FTPUSERNAME=%2 SET FTPPASSWORD=%3 SET LOCALDIR=%~f4 SET REMOTEDIR=%5 SET REMOTEFILE=%6 if "%FTPADDRESS%" == "" goto FTP_UPLOAD_USAGE if "%FTPUSERNAME%" == "" goto FTP_UPLOAD_USAGE if "%FTPPASSWORD%" == "" goto FTP_UPLOAD_USAGE if "%LOCALDIR%" == "" goto FTP_UPLOAD_USAGE if not defined REMOTEDIR goto FTP_UPLOAD_USAGE if not defined REMOTEFILE goto FTP_UPLOAD_USAGE :TEMP_NAME set TMPFILE=%TMP%\%RANDOM%_ftpupload.tmp if exist "%TMPFILE%" goto TEMP_NAME echo user %FTPUSERNAME% %FTPPASSWORD% > %TMPFILE% echo bin >> %TMPFILE% echo lcd %LOCALDIR% >> %TMPFILE% echo cd "%REMOTEDIR%" >> %TMPFILE% echo mget "%REMOTEFILE%" >> %TMPFILE% echo quit >> %TMPFILE% ftp -n -i "-s:%TMPFILE%" %FTPADDRESS% del %TMPFILE% goto FTP_UPLOAD_EXIT :FTP_UPLOAD_USAGE echo Usage: ftpget [address] [username] [password] [local directory] [remote directory] [remote file pattern] echo. :FTP_UPLOAD_EXIT set FTPADDRESS= set FTPUSERNAME= set FTPPASSWORD= set LOCALDIR= set REMOTEFILE= set REMOTEDIR= set TMPFILE= set CURRENT_DIRECTORY= set RELATIVE_DIRECTORY= @echo on 

我有一个类似的问题 – 像原来的海报,我想自动化file upload,但我不知道如何。 因为这是在我家的商店的注册terminal,我不想安装PowerShell(虽然这看起来像一个简单的select),只是想要一个简单的.bat文件来做到这一点。 这几乎是和其他用户说的一样。 我是新来的这个东西,所以这里有一个更详细的例子和解释(也感谢http://www.howtogeek.com/howto/windows/how-to-automate-ftp-uploads-from-the-windows-命令行/谁解释了如何用一个;.bat文件做到这一点。)

基本上你需要2个文件 – 一个.bat和一个.txt。 .bat告诉ftp.exe使用什么开关。 .txt给出了ftp.exe的命令列表。 在文本文件中把这个:

 username password cd whereverYouWantToPutTheFile lcd whereverTheFileComesFrom put C:\InventoryExport\inventory.test (or your file path) bye 

保存在任何你想要的地方。 在BAT文件中:

 ftp.exe -s:C:\Windows\System32\test.txt destinationIP pause 

很显然,在-s之后改变path到任何你的文本文件。 当你真的在运行的时候暂停一下 – 只是这样你才能看到任何错误。 当然,您可以在.txt文件中使用“get”或任何其他ftp命令来执行您需要执行的任何操作。

我不是肯定的,你需要在文本文件中的lcd命令,就像我说我是新来的使用命令行的这种types的东西,但这是为我工作。

我也遇到了同样的问题,并用类似于上面提到的Cheeso的解决scheme来解决这个问题。

“不起作用,说密码是srequire,尝试了几种不同的方式”

是的,这是因为通过命令文件的FTP会话不需要以string“user”开头的用户名。 放下它,然后尝试一下。

或者,你可能会看到这个,因为你的FTP命令文件没有正确的编码(这也是我)。 这是在运行时生成FTP命令文件的蹩脚部分。 Powershell的out-file cmdlet没有Windows FTP可以接受的编码选项(至less没有我能find的选项)。

无论如何,做一个WebClient.DownloadFile是要走的路。

手动尝试:

 $ ftp www.domainhere.com > useridhere > passwordhere > put test.txt > bye > pause 

这个脚本生成命令文件,然后将命令文件传送给ftp程序,沿途创build一个日志。 最后打印原始的bat文件,命令文件和这个会话的日志。

 @echo on @echo off > %0.ftp ::== GETmy!dir.bat >> %0.ftp echo a00002t >> %0.ftp echo iasdad$2 >> %0.ftp echo help >> %0.ftp echo prompt >> %0.ftp echo ascii >> %0.ftp echo !dir REPORT.CP1C.ROLLEDUP.TXT >> %0.ftp echo get REPORT.CP1C.ROLLEDUP.TXT >> %0.ftp echo !dir REPORT.CP1C.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir CONTENT.CP1C.ROLLEDUP.TXT >> %0.ftp echo get CONTENT.CP1C.ROLLEDUP.TXT >> %0.ftp echo !dir CONTENT.CP1C.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir WORKLOAD.CP1c.ROLLEDUP.TXT >> %0.ftp echo get WORKLOAD.CP1C.ROLLEDUP.TXT >> %0.ftp echo !dir WORKLOAD.CP1C.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir REPORT.TMMC.ROLLEDUP.TXT >> %0.ftp echo get REPORT.TMMC.ROLLEDUP.TXT >> %0.ftp echo !dir REPORT.TMMC.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir CONTENT.TMMC.ROLLEDUP.TXT >> %0.ftp echo get CONTENT.TMMC.ROLLEDUP.TXT >> %0.ftp echo !dir CONTENT.TMMC.ROLLEDUP.TXT >> %0.ftp echo ************************************************** >> %0.ftp echo !dir WORKLOAD.TMMC.ROLLEDUP.TXT >> %0.ftp echo get WORKLOAD.TMMC.ROLLEDUP.TXT >> %0.ftp echo !dir WORKLOAD.TMMC.ROLLEDUP.TXT >> %0.ftp echo quit ftp -d -v -s:%0.ftp 150.45.12.18 > %0.log type %0.bat type %0.ftp type %0.log