Net::SFTP is a pure-Ruby implementation of the SFTP protocol. That’s “SFTP” as in “Secure File Transfer Protocol”, as defined as an adjuct to the SSH specification. Not “SFTP” as in “Secure FTP” (a completely different beast). Nor is it an implementation of the “Simple File Transfer Protocol” (which is in no way secure).
Something like this:
require 'net/sftp'
Net::SFTP.start(host, user, password) do |sftp|
...
end
Net::SFTP.start
accepts the same parameters as Net::SSH.start
,
so I’ll direct you to that documentation for all the particulars.
You can piggy-back an SFTP connection on an existing Net::SSH connection, which can be useful if you’ve already got an SSH connection that you’re using for port forwarding or whatever.
require 'net/ssh'
require 'net/sftp'
Net::SSH.start(host, user, password) do |ssh|
...
ssh.sftp.connect do |sftp|
...
end
...
end
Assuming you already have an SFTP connection:
sftp.put_file "/path/to/local.file", "/path/to/remote.file"
Assuming you already have an SFTP connection, and your data is stored
in a string named data
:
sftp.open_handle("/path/to/remote.file", "w") do |handle|
result = sftp.write(handle, data)
puts result.code # the result of the operation
end
If (for whatever reason) you’d rather not use blocks, you can do
without, but be sure to call close_handle
when you’re done:
handle = sftp.open_handle("/path/to/remote.file", "w")
result = sftp.write(handle, data)
puts result.code # the result of the operation
sftp.close_handle(handle)
Assuming you already have an SFTP connection:
sftp.get_file "/path/to/remote.file", "/path/to/local.file"
Assuming you already have an SFTP connection:
data = nil
sftp.open_handle("/path/to/remote.file") do |handle|
data = sftp.read(handle)
end
You can specify both a “chunk size” and a “progress callback”. The callback will be invoked for every “chunk size” bytes that are received:
sftp.open_handle("/path/to/remote.file") do |handle|
begin
STDOUT.sync = true
data = sftp.read(handle, :chunk_size => 4096,
:progress_callback => lambda { |data| print "." })
puts
ensure
STDOUT.sync = false
end
end
File permissions are one of the stat
attributes of files and
directories:
p sftp.stat("/path/to/remote.file").permissions
Just use setstat
to change the permissions of an existing file:
sftp.setstat("/path/to/remote.file", :permissions => 0644)
If you have a handle for the remote file, you can use fstat
and
fsetstat
to query and set the permissions:
sftp.open_handle("/path/to/remote.file") do |handle|
permissions = sftp.fstat(handle)
sftp.fsetstat(handle, :permissions => permissions | 0444)
end
You query the contents of a directory by calling opendir
to obtain
a handle to the directory, and then using readdir
on the handle to
obtain a list of directory entries. Be sure to close the handle when
you’re done:
handle = sftp.opendir("/usr/lib")
items = sftp.readdir(handle)
items.each do |item|
puts item.filename
puts item.longname
p item.attributes # permissions, atime, etc.
end
sftp.close_handle(handle)
Use mkdir
:
sftp.mkdir("/path/to/remote/dir", :permissions => 0500)
Use rmdir
:
sftp.rmdir("/path/to/remote/dir")
Use remove
:
sftp.remove("/path/to/remote.file")
Use rename
:
sftp.rename("/path/to/remote.file", "/path/to/new.file")
It should be noted that rename
is only supported by version 2 or
later of the SFTP protocol, so if you’re using an older SFTP server you
might not be able to use this operation.