Метод 1. Одна из полезных и удобных особенностей PowerShell – возможность прозрачно взаимодействовать с утилитами командной строки.
В Windows досточно много утилит командной строки, которые уже много лет служат верой и правдой. Многие утилиты хорошо известны и широко используются. Некоторые решают свою задачу быстро и эффективно. Cовершенно неоправдано ожидать, что PowerShell заменит их сразу и полностью. В ряде случаев такая замена вообще неоправдана. Хорошо, что PowerShell не требует от нас переписывать существующие утилиты на .NET Framework и позволяет использовать всю их мощь.
Одна из таких утилит ftp.exe Утилита специфическая и по современным понятиям неудобная. Но она стандартная и администратор может ее использовать при необходимости на любой системе без лишних усилий. Чтобы несколько уменьшить неуклюжесть интерфейса утилиты ftp.exe , используем PowerShell.
Конечно мы не будем делать универсальную обертку: просто продемонстрируем технику и за одно решим вполне практическую задачу копирования списка файлов с ftp-сервера: сделать это стандартными командами вручную непросто (написать 5 команд get еще можно, а 15 уже утомительно).
Для начала создадим список команд в переменной (каждая команда пишется на новой строке!):
>$FileList = "open 17.17.17.21
user USERNAME PASSWORD
binary
cd DIRECTORYNAME
mdir * -" | ftp -i -n | where {$_.Trim() -ne "" }
В результате получим листинг нужной директории. Обратите внимание, что использована команда “mdir * — “ – звездочка, пробел, минус. Далее убраны пустые строки. Для конкретного ftp-сервера возможно придется убрать иной мусор.
Получив список файлов, мы можем использовать PowerShell для его предварительной обработки и фильтрации, чтобы выбрать нужные нам файлы для последующего копирования, например за определенную дату:
>$FileList = $FileList | Where {-not $_.StartsWith("d")} | Where {$_.Contains("Dec 22 2005")} | %{ $_.SubString(49) }
Тут сначала убраны директории, затем выбраны файлы за определенную дату, а потом вырезаны имена файлов.
Теперь скопируем эти файлы на локальную машину:
>$cmd = " open 17.17.17.21
user USERNAME PASSWORD
binary
cd DIRECTORYNAME
" +
($FileList | %{ "get ""$_""`n" })
$cmd | ftp -i –n
Как видите утилита ftp принимает команды через стандартный поток ввода и выдает результат на стандартный поток вывода. Эта ее особенность использована в приведенном примере.
Примечание.Некоторые утилиты не могут принимать команды через стандартный поток, но могут принимать команды из файла. В этом случае нам придется создать вспомогательный файл команд. Аналогичная ситуация может возникнуть с выводом результатов в файл.
Конечно приведенную технику можно использовать не только для загрузки файлов, но и для выгрузки на сервер: достаточно изменить команду get на команду put.
Метод 2. Другой метод работы с FTP сервером – использовать средства .NET Framework.
Получить список файлов (DIR):
>$server = "17.17.17.21"
>$filename = "DIRECTORY"
>$url = ftp://$server/$filename
>[System.Net.FtpWebRequest]$WR = [System.Net.WebRequest]::Create($url)
>$WR.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails
>$WR.Proxy = $null
>$WR.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")
>$WRStream = $WR.GetResponse();
>$responseStream = $WRStream.GetResponseStream()
>$readStream = new-object System.IO.StreamReader($responseStream, [System.Text.Encoding]::UTF8)
>$FileList =$readStream.ReadToEnd()
>$FileList = $FileList.Split("`n`r")
Примечание. Получить список методов для запросов:
>[System.Net.WebRequestMethods+FTP].GetMembers() | ft Name
Отфильтровать список файлов и получить только нужные файлы:
> $FileList = $FileList | Where {-not $_.StartsWith("d")} | Where {$_.Contains("Dec 22 2005")} | %{ $_.SubString(49) }
Загрузить файлы по сформированному списку:
>$FileList | % {
[System.Net.FtpWebRequest]$WR = [System.Net.WebRequest]::Create($url+"/$_")
$WR.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile
$WR.Proxy = $null
$WR.UseBinary = $True
$WR.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")
$WRStream = $WR.GetResponse()
$responseStream = $WRStream.GetResponseStream()
$readStream = new-object System.IO.StreamReader($responseStream, [System.Text.Encoding]::UTF8)
$a=$readStream.ReadToEnd()
Out-File -FilePath $_ -inputobject $a }
Обратная задача – выгрузка файлов по списку на сервер (не тестировано):
>$FileList | % {
[System.Net.FtpWebRequest]$WR = [System.Net.WebRequest]::Create($url+"/$_")
$WR.Method = [System.Net.WebRequestMethods+FTP]::UploadFile
$WR.Proxy = $null
$WR.UseBinary = $True
$WR.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")
$WRStream = $WR.GetResponse()
$responseStream = $WRStream.GetResponseStream()
$WriteStream = new-object System.IO.StreamWriter($responseStream, [System.Text.Encoding]::UTF8)
Get-Content $_ | % {$WriteStream.WriteString($_)
$WriteStream.Close()
$responseStream.Close()
$WRStream.Close()}
Загрузку одиночного файла можно выполнить более экономным методом. Для этого можно применить класс WebClient Class:
>$WC = new-object System.Net.WebClient
>$server = "17.17.17.21"
>$filename = "DIRECTORY/FILENAME"
>$url = "ftp://$server/$filename"
>$WC.Proxy = $null
>$Wc.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")
>$localfile = "LOCALFILENAME"
>$WC.DownloadFile($url,$localfile)
Для выгрузки файла на сервер надо поменять последнюю строку:
>$WC. UploadFile($url,$localfile)
Метод 3. Загрузить и установить какое-нибудь дополнение к PowerShell для работы с сетью. Есть коммерческие варианты. Есть бесплатные (Indy). Примеры смотрите в самих пакетах.
Заключение. Как видите, написание кода несколько более объемная задача, чем использование утилиты с хорошо продуманным интерфейсам. Впрочем это верно и для командлетов. Вывод напрашивается сам собой: PowerShell позволяет нам использовать всю мощь .NET Framework, но иногда мощь языка программирования нам лишняя: если есть удобная утилита, то в большинстве случаев ее можно использовать в PowerShell легко, просто и удобно получая компактный и быстрый скрипт для решения задачи.
Источники:
1. http://feelingsofwhite.com/2007/03/look-what-you-can-do-in-powershell-ftp/
4. WebRequestMethods.Ftp Class (как работать с вложенными классами http://blogs.msdn.com/powershell/archive/2009/08/27/plus-in-net-class-names.aspx )
Filed under: Без рубрики |
А как можно удалить файл к которому лезем по FTP/
Вызов метода удаления файла в контексте статьи $WR.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile