バッチファイルを作成して、ファイルをFTPサーバーにアップロードしようとしています。手動で入力すると問題なく動作しますが、バッチファイルを実行すると、接続後に停止します...
connected to domain.com.
220 Microsoft ftp server
User(domain.com:(none)):
その後、何も。ここで一体何が起こっているのでしょうか?
以下が私のバッチファイルです。
ftp www.domainhere.com
user useridhere
passwordhere
put test.txt
bye
pause
元のポスターが想像した方法でFTPセッションのスクリプトを作成することは合理的な考えであり、それはExpectが支援する一種のことです。 Windowsのバッチファイルではこれを行えません。
ただし、cURLやExpectを実行するよりも、PowershellとのFTP対話をスクリプト化する方が簡単な場合があります。これは、FTPサーバーに送信するテキストを直接スクリプト化しないという点で、異なるモデルです。代わりに、Powershellを使用して、FTPダイアログを生成するオブジェクトを操作します。
アップロード:
$File = "D:\Dev\somefilename.Zip"
$ftp = "ftp://username:[email protected]/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:[email protected]/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は、.batファイルを実行するcmd.exeのようなシェルです。しかし、Powershellは.ps1ファイルを実行し、かなり強力です。 PowershellはWindowsへの無料のアドオンであり、将来のバージョンのWindowsに組み込まれる予定です。 ここで入手 。
コマンドを使用してコマンドファイルを作成する
すなわち:commands.txt
open www.domainhere.com
user useridhere
passwordhere
put test.txt
bye
次に、コマンドラインからFTPクライアントを実行します。ftp-s:commands.txt
注:これは、Windows FTPクライアントで機能します。
編集:パスワードの前にユーザー名の後に改行が必要でした。
バッチファイルはそのようには機能しません。彼らはすべてを「タイプ」するのではなく、システムコマンドを実行します。この場合はftp
、それらが戻るのを待ち、次のコマンドを実行します...この場合、インタープリターは単にftp
で終了します。
mustを使用する場合は、ftp
コマンドを使用してから、スクリプトファイルを準備します(たとえば、commands.txt
およびftp -s:commands.txt
を実行します。
しかし、cURL、またはPHP/Perl/Python/whateverスクリプトを使用することをお勧めします。
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
を使用してもうまく機能しません。したがって、これらのようなものを使用して、これらの状況を処理できます。
これらのスクリプトはWindowsのftp
コマンドで動作し、1つのコマンドからディレクトリ全体をアップロードおよびダウンロードできます。これにより、さまざまなシステムで使用する場合にかなりの信頼性が得られます。
基本的には、ダウンロード/ダウンロードするディレクトリ構造をマップし、対応する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
私は同様の問題を抱えていました-元のポスターのように、ファイルのアップロードを自動化したかったのですが、その方法がわかりませんでした。これは私の家族の店のレジスター端末にあるため、PowerShellをインストールしたくありません(簡単なオプションのように見えますが)、これを行うには単純な.batファイルが必要でした。これは、ほとんどの悲しみと別のユーザーの言ったことです。私はこのようなものに慣れていないので、ここに詳細な例と説明があります( http://www.howtogeek.com/howto/windows/how-to-automate-ftp-uploads-from-にも感謝しますthe-windows-command-line / 誰がたった1つの.batファイルでそれを行うかを説明しています。
基本的に、2つのファイルが必要です。1つの.batと1つの.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:の後のパスをテキストファイルがある場所に変更します。実際に実行しているときに一時停止を解除します-エラーを確認できるようにするためです。もちろん、.txtファイルで「get」またはその他のftpコマンドを使用して、必要なことを実行できます。
テキストファイルにlcdコマンドが必要であることはよくありません。この種のことでコマンドラインを使用するのは初めてだと言ったようですが、これは私のために機能しています。
私はこれと同じ問題を抱えていましたが、上記のCheesoが提供したものと同様のソリューションで解決しました。
「機能しない、パスワードが必要だと言って、いくつかの異なる方法で試してみた」
うん、それは、コマンドファイルを介したFTPセッションでは、ユーザー名の前に文字列「user」を付ける必要がないためです。落として、試してみてください。
または、FTPコマンドファイルが適切にエンコードされていないので、これが表示される可能性があります(それも私に噛みつきました)。これは、実行時にFTPコマンドファイルを生成することに関するお粗末な部分です。 Powershellのout-fileコマンドレットには、Windows FTPが受け入れるエンコードオプションがありません(少なくとも1つは見つかりません)。
とにかく、WebClient.DownloadFileを実行するのが最善の方法です。
このスクリプトはコマンドファイルを生成し、コマンドファイルをftpプログラムにパイプして、途中でログを作成します。最後に、元の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
手動で試してください:
$ ftp www.domainhere.com
> useridhere
> passwordhere
> put test.txt
> bye
> pause