title: PowerShell How can I delete a directory with FTP?
body: <p>From the <a href="https://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp_fields(v=vs.110).aspx" rel="nofollow noreferrer">this list</a> of Web Request Method Fields, I've successfully deleted files from my server via FTP, by basically filling in the guide on <a href="https://social.technet.microsoft.com/Forums/windowsserver/en-US/2e07df8a-c7cd-47be-8e13-35de9b9189a8/remove-files-on-ftp-site-with-powershell?forum=winserverpowershell" rel="nofollow noreferrer">this page</a> with minor alterations:</p>
  
  <pre><code>$url = "ftp://server.net/path/to/place/FILE.txt"
  $userName = "username"
  $password = "p@ssw0rd!"
  
  $ftpreq = [System.Net.FtpWebRequest]::create($url)
  $ftpreq.Credentials = New-Object System.Net.NetworkCredential($userName, $password)
  $ftpreq.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
  
  $ftpreq.GetResponse()
  </code></pre>
  
  <p>The file is named <code>FILE.txt</code>, the folder is named <code>FOLDER</code>.</p>
  
  <p>When I try to do something similar, but for a folder, I get PowerShell errors and 550 response.</p>
  
  <p>I've tried basically two variations on the file deletion method.</p>
  
  <h3>Try 1: Change URL to match folder name, keep method</h3>
  
  <p>Note that the folder I'm attempting to delete is next to the file I have already successfully deleted.</p>
  
  <pre><code>$url = "ftp://server.net/path/to/place/FOLDER"
  $userName = "username"
  $password = "p@ssw0rd!"
  
  $ftpreq = [System.Net.FtpWebRequest]::create($url)
  $ftpreq.Credentials = New-Object System.Net.NetworkCredential($userName, $password)
  $ftpreq.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
  
  $ftpreq.GetResponse()
  </code></pre>
  
  <blockquote>
    <p>Exception calling "GetResponse" with "0" argument(s): "The remote server returned an error: (550) File unavailable
    (e.g., file not found, no access).</p>
  </blockquote>
  
  <h3>Try 2: Change method</h3>
  
  <pre><code>$url = "ftp://server.net/path/to/place/FOLDER"
  $userName = "username"
  $password = "p@ssw0rd!"
  
  $ftpreq = [System.Net.FtpWebRequest]::create($url)
  $ftpreq.Credentials = New-Object System.Net.NetworkCredential($userName, $password)
  $ftpreq.Method = [System.Net.WebRequestMethods+Ftp]::RemoveDirectory
  
  $ftpreq.GetResponse()
  </code></pre>
  
  <blockquote>
    <p>Exception calling "GetResponse" with "0" argument(s): "The remote server returned an error: (550) File unavailable
    (e.g., file not found, no access)."</p>
  </blockquote>
  
  <hr>
  
  <h1>Solution Implemented</h1>
  
  <pre><code>function DeleteFtpFolder($url, $credentials)
  {
      $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(" ", 5, [System.StringSplitOptions]::RemoveEmptyEntries)
  
          $type = $tokens[2]
          $name = $tokens[3]
          $fileUrl = ($url + "/" + $name)
  
          if ($type -eq "&lt;DIR&gt;")
          {
              Write-Host "Found folder: $name"
  
              DeleteFtpFolder $fileUrl $credentials
  
              Write-Host "Deleting folder: $name"
              $deleteRequest = [Net.WebRequest]::Create($fileUrl)
              $deleteRequest.Credentials = $credentials
              $deleteRequest.Method = [System.Net.WebRequestMethods+FTP]::RemoveDirectory
              $deleteRequest.GetResponse() | Out-Null
          }
          else 
          {
              $fileUrl = ($url + "/" + $name)
              Write-Host "Deleting file: $name"
  
              $deleteRequest = [Net.WebRequest]::Create($fileUrl)
              $deleteRequest.Credentials = $credentials
              $deleteRequest.Method = [System.Net.WebRequestMethods+FTP]::DeleteFile
              $deleteRequest.GetResponse() | Out-Null
          }
      }
  }
  
  $credentials = New-Object System.Net.NetworkCredential($AzureFtpUsername, $AzureFtpPassword)
  $url = $AzureFtpUrl
  
  DeleteFtpFolder $url $credentials
  </code></pre>
  
  <p>The setup is an embedded PowerShell script inside a process step inside Octopus Deploy.  That's why I call the function at the bottom.</p>
  
  <p>This solution is nearly identical to the <a href="https://stackoverflow.com/a/50148863/726336">accepted answer</a>, with some minor alterations on where I put the recursive call and how the returned data from the server gets parsed.  His solution seems like it looks more like an <code>ls</code> output, with more columns, whereas mine looked somewhat more like a <code>dir</code> output, with fewer columns.  But even then, it didn't look like the <code>dir</code> output on my local windows machine, so I'm not really sure exactly what is going on.  But it works, so that's good enough.</p>