FTPサーバーからすべてのファイルおよびサブフォルダーをダウンロードするPowerShellスクリプトを作成するのが好きです。 1つの特定のフォルダーからすべてのファイルをダウンロードするスクリプトを見つけましたが、サブフォルダーとそのファイルもダウンロードするのが好きです。
#FTP Server Information - SET VARIABLES
$ftp = "ftp://ftp.abc.ch/"
$user = 'abc'
$pass = 'abc'
$folder = '/'
$target = "C:\LocalData\Powershell\"
#SET CREDENTIALS
$credentials = new-object System.Net.NetworkCredential($user, $pass)
function Get-FtpDir ($url,$credentials) {
$request = [Net.WebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
if ($credentials) { $request.Credentials = $credentials }
$response = $request.GetResponse()
$reader = New-Object IO.StreamReader $response.GetResponseStream()
$reader.ReadToEnd()
$reader.Close()
$response.Close()
}
#SET FOLDER PATH
$folderPath= $ftp + "/" + $folder + "/"
$Allfiles=Get-FTPDir -url $folderPath -credentials $credentials
$files = ($Allfiles -split "`r`n")
$files
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
$counter = 0
foreach ($file in ($files | where {$_ -like "*.*"})){
$source=$folderPath + $file
$destination = $target + $file
$webclient.DownloadFile($source, $target+$file)
#PRINT FILE NAME AND COUNTER
$counter++
$counter
$source
}
ご協力いただきありがとうございます (:
.NET FrameworkまたはPowerShellは、再帰的なファイル操作(ダウンロードを含む)を明示的にサポートしていません。再帰を自分で実装する必要があります。
トリッキーな部分は、サブディレクトリからファイルを識別することです。 .NET Framework(FtpWebRequest
またはWebClient
)を使用して移植可能な方法でこれを行う方法はありません。残念ながら、.NETFrameworkはMLSD
コマンドをサポートしていません。これは、FTPプロトコルでファイル属性を使用してディレクトリリストを取得する唯一の移植可能な方法です。参照 FTPサーバー上のオブジェクトがファイルまたはディレクトリであるかどうかの確認 。
オプションは次のとおりです。
LIST
command = ListDirectoryDetails
method)を使用して、サーバー固有のリストを解析しようとします。多くのFTPサーバーは* nixスタイルのリストを使用します。このリストでは、エントリの最初にあるd
でディレクトリを識別します。しかし、多くのサーバーは異なるフォーマットを使用しています。次の例では、このアプローチを使用しています(* nix形式を想定)function DownloadFtpDirectory($url, $credentials, $localPath)
{
$listRequest = [Net.WebRequest]::Create($url)
$listRequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
$listRequest.Credentials = $credentials
$lines = New-Object System.Collections.ArrayList
$listResponse = $listRequest.GetResponse()
$listStream = $listResponse.GetResponseStream()
$listReader = New-Object System.IO.StreamReader($listStream)
while (!$listReader.EndOfStream)
{
$line = $listReader.ReadLine()
$lines.Add($line) | Out-Null
}
$listReader.Dispose()
$listStream.Dispose()
$listResponse.Dispose()
foreach ($line in $lines)
{
$tokens = $line.Split(" ", 9, [StringSplitOptions]::RemoveEmptyEntries)
$name = $tokens[8]
$permissions = $tokens[0]
$localFilePath = Join-Path $localPath $name
$fileUrl = ($url + $name)
if ($permissions[0] -eq 'd')
{
if (!(Test-Path $localFilePath -PathType container))
{
Write-Host "Creating directory $localFilePath"
New-Item $localFilePath -Type directory | Out-Null
}
DownloadFtpDirectory ($fileUrl + "/") $credentials $localFilePath
}
else
{
Write-Host "Downloading $fileUrl to $localFilePath"
$downloadRequest = [Net.WebRequest]::Create($fileUrl)
$downloadRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$downloadRequest.Credentials = $credentials
$downloadResponse = $downloadRequest.GetResponse()
$sourceStream = $downloadResponse.GetResponseStream()
$targetStream = [System.IO.File]::Create($localFilePath)
$buffer = New-Object byte[] 10240
while (($read = $sourceStream.Read($buffer, 0, $buffer.Length)) -gt 0)
{
$targetStream.Write($buffer, 0, $read);
}
$targetStream.Dispose()
$sourceStream.Dispose()
$downloadResponse.Dispose()
}
}
}
次のような関数を使用します。
$credentials = New-Object System.Net.NetworkCredential("user", "mypassword")
$url = "ftp://ftp.example.com/directory/to/download/"
DownloadFtpDirectory $url $credentials "C:\target\directory"
コードは私のC#の例から翻訳されています C#FTP経由ですべてのファイルとサブディレクトリをダウンロードします 。
ただし Microsoftは新しい開発にFtpWebRequest
を推奨していません 。
サーバー固有のディレクトリリスト形式の解析に関する問題を回避したい場合は、MLSD
コマンドをサポートするサードパーティライブラリを使用するか、さまざまなLIST
リスト形式を解析してください。再帰的なダウンロード。
たとえば、 WinSCP .NET Assembly を使用すると、 Session.GetFiles
を1回呼び出すだけでディレクトリ全体をダウンロードできます。
# Load WinSCP .NET Assembly
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Ftp
HostName = "ftp.example.com"
UserName = "user"
Password = "mypassword"
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Download files
$session.GetFiles("/directory/to/download/*", "C:\target\directory\*").Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
内部的には、サーバーでサポートされている場合、WinSCPはMLSD
コマンドを使用します。そうでない場合は、LIST
コマンドを使用し、数十の異なるリスト形式をサポートします。
Session.GetFiles
メソッド はデフォルトで再帰的です。
(私はWinSCPの作者です)
PowerShellを介してFTPからファイル/フォルダーを取得するために、いくつかの関数を作成しました。FTPから非表示のものも取得できます。
特定のフォルダー内のすべてのファイルとサブフォルダー(非表示のものも含む)を取得する例:
Get-FtpChildItem -ftpFolderPath "ftp://myHost.com/root/leaf/" -userName "User" -password "pw" -Directory -File
3番目のライブラリをインストールしなくても、次のモジュールから関数をコピーできます。 https://github.com/AstralisSomnium/PowerShell-No-Library-Just-Functions/blob/master/FTPModule.ps1 ==
AstralisSomnium
PowerShellを介してFTPからファイル/フォルダーを取得するために、いくつかの関数を作成しました。FTPから非表示のものも取得できます。
特定のフォルダー内のすべてのファイルとサブフォルダー(非表示のものも含む)を取得する例:
Get-FtpChildItem -ftpFolderPath " ftp://myHost.com/root/leaf/ " -userName "User" -password "pw" -Directory-File次のモジュールから関数をコピーするだけです。 3番目のライブラリをインストールする必要はありません: https://github.com/AstralisSomnium/PowerShell-No-Library-Just-Functions/blob/master/FTPModule.ps1
はい、でもダウンロードしたファイルの宛先はどこに書きますか?
Martin Prikryl
運が良ければ、特定のケースでは、ファイル名でディレクトリからファイルを区別できます(つまり、すべてのファイルに拡張子が付いていますが、サブディレクトリには拡張子がありません)
このオプションを使用すると思いますが、「。*」のようなものを作成してすべての拡張子を選択できますか?