1 (изменено: svk.78, 2018-06-19 10:46:12)

Тема: CMD/BAT:проверка наличия файла в FTP директории

есть на фтп 53шт директории, куда каждый вечер/утро выкладывается файл.
Приходится через Total Commander заходить в каждую директорию и проверять есть ли за вчерашнюю дату файл и какой его размер.
Выходит задача создать скрипт, который бы выводил список: директория (отображать можно верхнюю а не все вложенные), имя файла, дата файла, размер.
При этом дата может оказаться не вчерашняя, а позавчерашняя, т.к. например файл не выложен. В целом результат в виде таблицы/списка - папка, имя, дата, размер - устроило бы.

В скриптах я ноль. Посоветуйте как реализовать и где копать. Может это будет vbs, а может и батник. Гуглил долго, но близкого ничего не нашел. Может кто подскажет?

2

Re: CMD/BAT:проверка наличия файла в FTP директории

Доброго.
Название темы поправьте (там должен быть язык).

svk.78 пишет:

Выходит задача создать скрипт, который бы выводил список: директория (отображать можно верхнюю а не все вложенные), имя файла, дата файла, размер.

Здесь лежит полуготовый скрипт. При работе он сохраняет листинги найденных директорий (размер, дата, тип - файл или директория, ну и имя там есть).
В общем - вы плохо искали.

3

Re: CMD/BAT:проверка наличия файла в FTP директории

UNDYING пишет:

Доброго.
Название темы поправьте (там должен быть язык).

svk.78 пишет:

Выходит задача создать скрипт, который бы выводил список: директория (отображать можно верхнюю а не все вложенные), имя файла, дата файла, размер.

Здесь лежит полуготовый скрипт. При работе он сохраняет листинги найденных директорий (размер, дата, тип - файл или директория, ну и имя там есть).
В общем - вы плохо искали.

про язык не понял...
возможно я сумбурно объяснил что мне нужно, то вот более подробное объяснение:
есть 53шт. папки на фтп. В каждую папку каждый день падает файл типа pos1_171003_0851.rep или не падает.
хотелось бы написать скрипт или воспользоваться готовым, чтобы на экран выводился список вчера выложенных в папки файлов.
В итоге должно появиться окно в котором я увижу 53 строчки данных: папка фтп, имя файла (последнего закачанного в папку), дата файла, размер файла

примерно так:
/FTP/papka1/ pos1_171003_0851.rep 19.06.18 512Kb
/FTP/papka2/ pos1_180618_2251.rep 19.06.18 675Kb
/FTP/papka3/ pos1_170618_1851.rep 18.06.18 35Kb
/FTP/papka4/ pos1_171003_0851.rep 19.06.18 215Kb

т.е. должна быть возможность указать конкретную папку, точнее список папок на фтп для опроса.

4

Re: CMD/BAT:проверка наличия файла в FTP директории

svk.78 пишет:

про язык не понял...

"Обязательно прочитать перед созданием темы!"

svk.78 пишет:

хотелось бы написать скрипт или воспользоваться готовым, чтобы на экран выводился список вчера выложенных в папки файлов

Подключитесь к серверу "ручками" через ftp.exe, введите:


dir .

Получите нужный вам список для текущей директории.

5

Re: CMD/BAT:проверка наличия файла в FTP директории

Получите нужный вам список для текущей директории.

но мне не надо содержимое всей директории! т.к. там много файлов. Мне нужен только последний (свежий) и директорий будет 53шт. т.е. из каждой по файлу вывести в список...

6

Re: CMD/BAT:проверка наличия файла в FTP директории

svk.78 пишет:

но мне не надо содержимое всей директории! т.к. там много файлов. Мне нужен только последний (свежий) и директорий будет 53шт.

ftp.exe не умеет делать выборочные списки файлов - либо всё содержимое директории, без поддиректорий, либо ничего.
Алгоритм, приблизительно, такой:

  • Получаем список директорий

  • Получаем список файлов для всех директорий (это придётся делать для каждой директории отдельно)

  • Фильтруем список файлов (берём каждый первый или с текущей датой)

  • Скачиваем нужные файлы

Как-то иначе вряд ли получится (если использовать входящий в состав Windows ftp.exe).
Ну и ftp.exe не умеет строить рекурсивный список содержимого ftp-сервера. Поэтому и приходится сначала получать списки всех файлов, выбирать нужные и только потом их скачивать.
Подключитесь к своему FTP-серверу используя ftp.exe (в интерактивном режиме) и наберите help - получите весь список команд, которые поддерживает ваш FTP-сервер (их там, мягко говоря, негусто, и каждая из команд ещё повторяется 2-4 раза под другим именем - реальный список раза в 3 короче).

Microsoft Windows [Version 6.1.7601]
(c) Корпорация Майкрософт (Microsoft Corp.), 2009. Все права защищены.

C:\Users\user>ftp
ftp> open ftp.adobe.com
Связь с ftpgen.wip4.adobe.com.
220 Welcome to Adobe FTP services
Пользователь (ftpgen.wip4.adobe.com:(none)): ftp
331 Please specify the password.
Пароль:
230 Login successful.
ftp> help
Допускается сокращение команд при вводе.  Набор команд:

!               delete          literal         prompt          send
?               debug           ls              put             status
append          dir             mdelete         pwd             trace
ascii           disconnect      mdir            quit            type
bell            get             mget            quote           user
binary          glob            mkdir           recv            verbose
bye             hash            mls             remotehelp
cd              help            mput            rename
close           lcd             open            rmdir
ftp>

Если количество и имена директорий фиксированные, то можно получить список всех файлов за 1 раз, после чего отфильтровать по дате и сформировать список файлов на скачку с ftp-сервера.

Если хотите что-то лучше, удобнее, и т.п. - возьмите Powershell, Perl, Python или что-то ещё и пишите на них, используя готовые модули/библиотеки для работы с FTP - код сократится до 10-15 строчек.

7

Re: CMD/BAT:проверка наличия файла в FTP директории

UNDYING пишет:

Если хотите что-то лучше, удобнее, и т.п. - возьмите Powershell, Perl, Python или что-то ещё и пишите на них, используя готовые модули/библиотеки для работы с FTP - код сократится до 10-15 строчек.

Вот пример на Powershell:

$Server = "ftp://ftp.example.com"
$User = "user"
$Pass = "password"
$destpath = "C:\"
$list = List-FTPDir -URL $Server -Username $User -Password $Pass | ?{$_.ModifiedDate -gt (Get-date).AddDays(-1) -and $_.IsDirectory -eq $false}
$list | %{Get-FTPFile -URL $_.FullPath -Username $User -Password $Pass -Target $destpath}

Где функции List-FTPDir и Get-FTPFile взяты из готовой библиотеки.

И полный листинг:

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
    )
    #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; }
        }
    }
    
    #Create stream reader and initialize return array
    $reader = New-Object IO.StreamReader $response.GetResponseStream()
    $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.example.com"
$User = "user"
$Pass = "password"
$destpath = "C:\"
$list = List-FTPDir -URL $Server -Username $User -Password $Pass | ?{$_.ModifiedDate -gt (Get-date).AddDays(-1) -and $_.IsDirectory -eq $false}
$list | %{Get-FTPFile -URL $_.FullPath -Username $User -Password $Pass -Target $destpath}

8

Re: CMD/BAT:проверка наличия файла в FTP директории

UNDYING

Скопировал "полный листинг" в файл и
проставил внизу фтп ftp.shtrih-m.ru запустил скрипт, но в ответ получил ошибку

PS D:\> D:\proba.ps1
Get-FTPFile : Не удается привязать аргумент к параметру "URL", так как он представляет собой пустую строку.
D:\proba.ps1:233 знак:27
+ $list | %{Get-FTPFile -URL <<<<  $_.FullPath -Username $User -Password $Pass -Target $destpath}
    + CategoryInfo          : InvalidData: (:) [Get-FTPFile], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Get-FTPFile

9

Re: CMD/BAT:проверка наличия файла в FTP директории

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 "обломается" качать "кракозябры").