PoshCode Logo PowerShell Code Repository

Get-FtpList (modification of post by Joel Bennett view diff)
diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1692"></script>download | new post

A function to get a file listing via FTP and parse it into objects.

The default “FtpWebResponse“http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.aspx listing comes back in HTML format from my FTP server, and this function parses it into objects. However, the string parsing here may not work on the output of your FTP server (if so, please contribute by adding another set of parsing).

  1.  
  2. function Get-FtpList {
  3. #.Synopsis
  4. #  Read a list of files (and directories) from FTP
  5. #.Description
  6. #  An initial implementation of a string-parsing lister for FTP which converts lists to objects (in the one format that I've seen -- there are other formats)
  7. #
  8. #  This implementation will use whatever proxy is set up in the "Internet Options" proxy settings (usually your web proxy, and basically never an FTP server with USER@HOST settings), which may affect the file list format.
  9. #.Parameter Path
  10. #  The full path to the directory you want a listing from, in the form: ftp://servername/folder/
  11. #.Parameter Credentials
  12. #  The login credentials for the ftp server, if needed
  13. #.Example
  14. # $List = Get-FtpList "ftp://joelbennett.net/" (Get-Credential)
  15. # C:\PS>$list | ft Name, Type, Length, LastWriteTime, FullName -auto
  16. #
  17. # Name       Type      Length LastWriteTime         FullName                                                      
  18. # ----       ----      ------ -------------         --------                                                      
  19. # DeskOps    Directory        5/24/2009 12:00:00 AM ftp://joelbennett.net/DeskOps/                
  20. # GeoShell   Directory        5/24/2009 12:00:00 AM ftp://joelbennett.net/GeoShell/              
  21. # Jaykul.asc File      1626   5/24/2009 12:00:00 AM ftp://joelbennett.net/Jaykul.asc              
  22. # ShotGlass  Directory        5/24/2009 12:00:00 AM ftp://joelbennett.net/ShotGlass/              
  23. # images     Directory        2/6/2010 2:13:00 PM   ftp://joelbennett.net/images/    
  24. # index.php  File      407    5/9/2009 12:00:00 AM  ftp://joelbennett.net/index.php              
  25. #
  26. # Description
  27. # -----------
  28. # The first command gets a list of files, directories (and symlinks, if there are any) into $List
  29. # The second command outputs that list in a useable table format, because the Huddled.FtpItemInfo type hasn't been set up in my Format ps1xml files so by default the output will be in list form.
  30. #
  31. #.Notes
  32. #  This will use a proxy, but only if it's set up correctly in "Internet Options" proxy settings.
  33. #.Link
  34. # The FTP WebRequest class
  35. # *   http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx
  36. #.Link
  37. # The FTP Methods enumeration
  38. # *   http://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp.aspx
  39. #
  40. [CmdletBinding()]
  41. Param(
  42.    [Parameter(Mandatory=$true)]
  43.    [string]$Path
  44. ,
  45.    [Parameter(Mandatory=$false)]
  46.    [System.Net.ICredentials]$Credential
  47. )
  48.    
  49.    [System.Net.FtpWebRequest]$request = [System.Net.WebRequest]::Create($path)
  50.    $request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails
  51.    if($credential) { $request.Credentials = $credential }
  52.    $response = $request.GetResponse()
  53.    
  54.    if( $response.StatusCode -ne "CommandOK" ) {
  55.       throw "Response Status: $($response.StatusDescription)"
  56.    }
  57.    
  58.    $global:ftpOutputCache = (Receive-Stream $response.GetResponseStream())
  59.    $list = $global:ftpOutputCache -replace "(?:.|\n)*<PRE>\s+((?:.*|\n)+)\s+</PRE>(?:.|\n)*",'$1' -split "`n"
  60.    $( foreach($line in $list | ? { $_ }) {
  61.       [DateTime]$date, [string]$length, [string]$url, [string]$name, $null = $line -split ' + | <A HREF="|">|</A>'
  62.      
  63.       New-Object PSObject -Property @{
  64.          LastWriteTime = $date
  65.          FullName      = $path.trim().trim('/') + '/' + $url
  66.          Length        = $(if($length -eq (($length -as [int]) -as [string])) { [int]$length } else { $null })
  67.          Type          = $(if($length -eq (($length -as [int]) -as [string])) { "File" } else { $length })
  68.          Name          = $name
  69.       }
  70.    } # Note: I put a (fake) "Huddled.FtpItemInfo" type name on. You can use that for format.ps1xml
  71.    ) | Sort Type | %{ $_.PSTypeNames.Insert(0, "Huddled.FtpItemInfo"); $_ } | Write-Output  
  72. }
  73.  
  74.  
  75.  
  76. function Receive-Stream {
  77. #.Synopsis
  78. #  Read a stream to the end and close it
  79. #.Description
  80. #  Will read from a byte stream and output a string or a file
  81. #.Param reader
  82. #  The stream to read from
  83. #.Param fileName
  84. #  A file to write to. If this parameter is provided, the function will output to file
  85. #.Param encoding
  86. #  The text encoding, if you want to override the default.
  87. param( [System.IO.Stream]$reader, $fileName, $encoding = [System.Text.Encoding]::GetEncoding( $null ) )
  88.    
  89.    if($fileName) {
  90.       $writer = new-object System.IO.FileStream $fileName, "Create"
  91.    } else {
  92.       [string]$output = ""
  93.    }
  94.        
  95.    [byte[]]$buffer = new-object byte[] 4096
  96.    [int]$total = [int]$count = 0
  97.    do
  98.    {
  99.       $count = $reader.Read($buffer, 0, $buffer.Length)
  100.       if($fileName) {
  101.          $writer.Write($buffer, 0, $count)
  102.       } else {
  103.          $output += $encoding.GetString($buffer, 0, $count)
  104.       }
  105.    } while ($count -gt 0)
  106.  
  107.    $reader.Close()
  108.    if(!$fileName) { $output }
  109. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me