web-dev-qa-db-ja.com

FTPのアップロードおよびダウンロードをスクリプト化する方法は?

バッチファイルを作成して、ファイルを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
39
payling

元のポスターが想像した方法で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に組み込まれる予定です。 ここで入手

ソース: http://poshcode.org/1134

66
Cheeso

コマンドを使用してコマンドファイルを作成する

すなわち:commands.txt

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

次に、コマンドラインからFTPクライアントを実行します。ftp-s:commands.txt

注:これは、Windows FTPクライアントで機能します。

編集:パスワードの前にユーザー名の後に改行が必要でした。

26
cbeuker

バッチファイルはそのようには機能しません。彼らはすべてを「タイプ」するのではなく、システムコマンドを実行します。この場合はftp、それらが戻るのを待ち、次のコマンドを実行します...この場合、インタープリターは単にftpで終了します。

mustを使用する場合は、ftpコマンドを使用してから、スクリプトファイルを準備します(たとえば、commands.txtおよびftp -s:commands.txtを実行します。

しかし、cURL、またはPHP/Perl/Python/whateverスクリプトを使用することをお勧めします。

6
grawity

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
6
ruslander

これは古い質問であることは知っていますが、他の人を助けることを期待して、ここですでに答えに何かを追加したかったのです。

-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
2
Bryan Way

私は同様の問題を抱えていました-元のポスターのように、ファイルのアップロードを自動化したかったのですが、その方法がわかりませんでした。これは私の家族の店のレジスター端末にあるため、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コマンドが必要であることはよくありません。この種のことでコマンドラインを使用するのは初めてだと言ったようですが、これは私のために機能しています。

1
Josiah

私はこれと同じ問題を抱えていましたが、上記のCheesoが提供したものと同様のソリューションで解決しました。

「機能しない、パスワードが必要だと言って、いくつかの異なる方法で試してみた」

うん、それは、コマンドファイルを介したFTPセッションでは、ユーザー名の前に文字列「user」を付ける必要がないためです。落として、試してみてください。

または、FTPコマンドファイルが適切にエンコードされていないので、これが表示される可能性があります(それも私に噛みつきました)。これは、実行時にFTPコマンドファイルを生成することに関するお粗末な部分です。 Powershellのout-fileコマンドレットには、Windows FTPが受け入れるエンコードオプションがありません(少なくとも1つは見つかりません)。

とにかく、WebClient.DownloadFileを実行するのが最善の方法です。

0
user180562

このスクリプトはコマンドファイルを生成し、コマンドファイルを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 
0
ken klein

手動で試してください:

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