svk.78 пишет:но в ответ получил ошибку
Потому что список файлов на закачку получился пустым.
Function List-FTPDir {
<#
.SYNOPSIS
List-FTPDir lists the items in an FTP server's specified path
.DESCRIPTION
The function connects to the FTP server, retrieves a directory listing and then returns a hashtable with all the items along with included properties.
.PARAMETER URL
The URL of the FTP server
.PARAMETER Path
The subdirectory that you wish to receive a directory listing of. This can be blank.
.PARAMETER Username
The username to connect with. This can be blank.
.PARAMETER Password
The password to connect with. This can be blank.
.EXAMPLE
List-FTPDir -URL "ftp://ftp.microsoft.com" -Path "/DotNet" -Username "billgates" -Password "ballmer"
#>
Param(
[Parameter(Mandatory=$true)]
[string]$URL,
[string]$Path,
[string]$Username,
[string]$Password,
[string]$encoding="windows-1251"
)
#If there is a path, add it to the FTP URL
if ($path) {
$fullurl = $url + $path
}
else {
$fullurl = $url
}
#Create the FTP object
$request = [Net.WebRequest]::Create($fullurl)
$request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails
#Add authentication if needed
if ($username -and $password) {
$credentials = New-Object System.Net.NetworkCredential($username,$password)
$request.Credentials = $credentials
}
#Get response from FTP server
try {
$response = $request.GetResponse()
}
catch {
$response.Close()
switch -wildcard ($_) {
"*timed out*" { Write-Warning "FTP connection timed out"; break; }
default { Write-Warning $_; break; }
}
}
#encoding
$enc = [Text.Encoding]::GetEncoding($encoding)
#Create stream reader and initialize return array
$reader = New-Object IO.StreamReader ($response.GetResponseStream(), $enc)
$array = @()
#Read first line of stream
[string]$line = $reader.ReadLine()
#Loop through stream until end
while ($line) {
#Split line from stream in to parameters using regex voodoo
$null, [string]$IsDirectory, [string]$Flag, [string]$Link, [string]$UserName, [string]$GroupName, [string]$Size, [string]$Date, [string]$Name = `
[regex]::split($Line,'^([d-])([rwxt-]{9})\s+(\d{1,})\s+([.@A-Za-z0-9-]+)\s+([A-Za-z0-9-]+)\s+(\d{1,})\s+(\w+\s+\d{1,2}\s+\d{1,2}:?\d{2})\s+(.+?)\s?$',"SingleLine,IgnoreCase,IgnorePatternWhitespace")
#Check to see what the FTP software is to deal with quirks
if ($isdirectory -eq "") {
#Most likely dealing with IIS6, needs further regex voodoo
$null, [string]$NewDate, [string]$IsDirectory, [string]$Size, [string]$Name = `
[regex]::split($Line,'^(\d{2}-\d{2}-\d{2}\s+\d{2}:\d{2}[AP]M)\s+<*([DIR]*)>*\s+(\d*)\s+(.+).*$',"SingleLine,IgnoreCase,IgnorePatternWhitespace")
#Fallback for directory check
if ($isdirectory -eq "") {
$isdirectory = "-"
}
}
else {
#Used for IIS7 or Linux/UNIX FTP servers, less quirk workarounds
$DatePart = $Date -split "\s+"
$NewDateString = "$($DatePart[0]) $('{0:D2}' -f [int]$DatePart[1]) $($DatePart[2])"
try {
if($DatePart[2] -match ":") {
$Month = ([DateTime]::ParseExact($DatePart[0],"MMM",[System.Globalization.CultureInfo]::InvariantCulture)).Month
if((Get-Date).Month -ge $Month) {
$NewDate = [DateTime]::ParseExact($NewDateString,"MMM dd HH:mm",[System.Globalization.CultureInfo]::InvariantCulture)
}
else {
$NewDate = ([DateTime]::ParseExact($NewDateString,"MMM dd HH:mm",[System.Globalization.CultureInfo]::InvariantCulture)).AddYears(-1)
}
}
else
{
$NewDate = [DateTime]::ParseExact($NewDateString,"MMM dd yyyy",[System.Globalization.CultureInfo]::InvariantCulture)
}
}
catch {
#Just in case the above parsing fails
$newdate = "Parsing error"
}
}
#Return boolean for $isdirectory
switch ($isdirectory) {
"-" { $directory = $false }
"DIR" { $directory = $true }
"d" { $directory = $true }
}
$name = $name.Substring(0,$name.Length-1)
#Add full path variable
$fullpath = $fullurl + "/" + $name
#Add formatted object to return array
$array += [PSCustomObject]@{
"IsDirectory" = $directory
"Rights" = $flag
"Link" = $link
"User" = $username
"Group" = $groupname
"Size" = $size
"ModifiedDate" = $newdate
"Name" = $name
"FullPath" = $fullpath
}
#Read the next line of output
$line = $reader.ReadLine()
}
#Close stream reader and FTP connection
$reader.Close()
$response.Close()
#Return array
return $array
}
Function Get-FTPFile {
<#
.SYNOPSIS
Get-FTPFile downloads a file from an FTP server
.DESCRIPTION
The function connects to the FTP server and then downloads a file to the filesystem.
.PARAMETER URL
The URL of the file on the FTP server
.PARAMETER Username
The username to connect with. This can be blank.
.PARAMETER Password
The password to connect with. This can be blank.
.PARAMETER Target
The target folder for the downloaded file
.EXAMPLE
Get-FTPFile -URL "ftp://ftp.microsoft.com/DotNet/dotnet45.exe" -Username "billgates" -Password "ballmer" -Target "C:\Software"
#>
Param(
[Parameter(Mandatory=$true)]
[string]$URL,
[string]$Username,
[string]$Password,
[Parameter(Mandatory=$true)]
[string]$Target
)
#Test if the target folder exists
if (!(Test-Path $target -PathType Container)) {
Write-Warning "Target folder does not exist"
break
}
#Find the filename from the URL, then add to the local target
$filename = $url.split("/") | select -last 1
$fullpath = ($target + "\" + $filename) -Replace "\\","\"
#Create the FTP object
$request = [Net.WebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile
#Add authentication if needed
if ($username -and $password) {
$credentials = New-Object System.Net.NetworkCredential($username,$password)
$request.Credentials = $credentials
}
#Use binary mode, defaults to true
$request.UseBinary = $true
#Get response from FTP server
try {
$response = $request.GetResponse()
}
catch {
$response.Close()
switch -wildcard ($_) {
"*timed out*" { Write-Warning "FTP connection timed out"; break; }
"*550*" { Write-Warning "File unavailable (e.g., file not found, no access)"; break; }
default { Write-Warning $_; break; }
}
}
#Add the stream to a variable
$stream = $response.GetResponseStream()
$reader = New-Object IO.StreamReader $stream
try {
$targetfile = New-Object IO.FileStream ($fullpath,[IO.FileMode]::Create)
[byte[]]$readbuffer = New-Object byte[] 1024
#Write filestream to the file until all done
do {
$readlength = $stream.Read($readbuffer,0,1024)
$targetfile.Write($readbuffer,0,$readlength)
}
while ($readlength -ne 0)
#Close file
$targetfile.close()
#Close connection to FTP server
$reader.Close()
$response.Close()
}
catch {
$_
exit
}
}
$Server = "ftp://ftp.shtrih-m.ru/"
$User = "anonymous"
$Pass = "user@example.com"
$destpath = "D:\234"
$list = List-FTPDir -URL $Server -Username $User -Password $Pass | ?{$_.IsDirectory -eq $true} | %{List-FTPDir -URL $Server -Username $User -Password $Pass -Path $_.Name} | ?{$_.ModifiedDate -gt (Get-date).AddDays(-1) -and $_.IsDirectory -eq $false}
if ($list -eq $null) {
echo 'Список файлов пуст. Скачивать нечего.'
} else {
$list | %{Get-FTPFile -URL $_.FullPath -Username $User -Password $Pass -Target $destpath}
}
Код пройдёт все директории в корне (но не рекурсивно) и отберёт все файлы изменённые за последние сутки. На ftp://ftp.shtrih-m.ru/ таких нет.
За последние 100 дней там изменялся 1 файл.
$list = List-FTPDir -URL $Server -Username $User -Password $Pass | ?{$_.IsDirectory -eq $true} | %{List-FTPDir -URL $Server -Username $User -Password $Pass -Path $_.Name} | ?{$_.ModifiedDate -gt (Get-date).AddDays(-100) -and $_.IsDirectory -eq $false}
PS C:\Users\user> $list
IsDirectory : False
Rights : rw-r--r--
Link : 1
User : ftp
Group : ftp
Size : 120
ModifiedDate : 05.04.2018 13:15:00
Name : test.txt
FullPath : ftp://ftp.shtrih-m.ru/minipos/test.txt
Прочтите пару обучающих статей по Powershell - будете такие скрипты за 10-15 минут писать в любых количествах.
И обратите внимание, я дописал у функции List-FTPDir опцию кодировки (-Encoding, по умолчанию windows-1251), иначе тот же ftp.shtrih-m.ru вернёт кучу файлов и папок с кириллицей в имени "кракозябрами" (Get-FTPFile "обломается" качать "кракозябры").