2

I am trying to old delete files from an FTP using Ruby net/sftp, but I keep getting an error saying the file does not exist.

:error=>"Net::SFTP::StatusException (2, \"no such file\")"

I can manually delete files when logging in using the same creds, so I know I have permission.

require 'net/sftp'
ftp = Net::SFTP.start(@ftp_url, @ftp_user, :password =>  @ftp_pwd)
ftp.dir.entries('somePath').each do |entry|
    begin
      age_days = (Time.now.to_i - entry.attributes.atime) / 86400

      if(age_days > ftp_max_file_age_days)
        ftp.remove!(entry.name)
      end

    rescue Exception => e
      # log error here
    end
end

I prefer remove! so everything happens synchronously in this case, but I have also tried remove.

I also tried giving it the full path of the file instead of just the entry name (like 'somePath' + entry.name instead of just entry.name). I was thinking perhaps it was because I needed to change the working directory, which apparently net/sftp does not allow.

Thanks in advance!

theUtherSide
  • 3,338
  • 4
  • 36
  • 35
  • 1
    "I was thinking perhaps it was because I needed to change the working directory, which apparently net/sftp does not allow." The SFTP protocol doesn't actually have a command to change the remote directory. Clients with a cd/chdir operation are faking it. – Kenster Aug 23 '15 at 14:45

2 Answers2

1

Check if entry is a directory if yes then use ftp.rmdir. like below -

require 'net/sftp'
ftp = Net::SFTP.start(@ftp_url, @ftp_user, :password =>  @ftp_pwd)
ftp.dir.entries('somePath').each do |entry|
  begin
    age_days = (Time.now.to_i - entry.attributes.atime) / 86400

    if(age_days > ftp_max_file_age_days)
      if File.directory?(entry.name)
        ftp.rmdir(entry.name) 
      else         
        ftp.remove!(entry.name)
      end
    end

  rescue Exception => e
    # log error here
  end
end
Vishnu Atrai
  • 2,370
  • 22
  • 24
1

We were eventually able to delete files using the remove method (instead of remove!.) We made a small change to the way we provide the password.

We confirmed that permissions on the FTP did not change, so I think using non_interactive: true may have been the trick.

require 'net/sftp'

def self.delete_report(endpoint, username, password, report_filename)
  SSH_OPTIONS = { non_interactive: true }.freeze
  report_filename_base = File.basename(report_filename, '.*')

  Net::SFTP.start(endpoint, username, SSH_OPTIONS.merge(password: password)) do |sftp|
    sftp.remove(report_filename)
    sftp.remove("#{report_filename_base}.fin")
    sftp.remove("processed/#{report_filename}")
    sftp.remove("processed/#{report_filename_base}.fin")
    sftp.remove("failed/#{report_filename}")
    sftp.remove("failed/#{report_filename_base}.fin")
    sftp.remove("failed/#{report_filename_base}.info")
  end

I still don't fully understand why the same method did not work before, but we're able to delete files in subfolders too, as shown in this example.

theUtherSide
  • 3,338
  • 4
  • 36
  • 35