There are some quirks in this library that make this recursive list complex, because the interaction between ChangeDirectory and ListDirectory does not work as you might expect.
The following is not a list of files in the / home directory, but a list of files in the / (root) directory:
sftp.ChangeDirectory("home"); sftp.ListDirectory("").Select (s => s.FullName);
The following fails and returns a SftpPathNotFoundException:
sftp.ChangeDirectory("home"); sftp.ListDirectory("home").Select (s => s.FullName);
The following is the correct way to list files in the / home directory
sftp.ChangeDirectory("/"); sftp.ListDirectory("home").Select (s => s.FullName);
This is pretty crazy if you ask me. Setting the default directory using the ChangeDirectory method ChangeDirectory not affect the ListDirectory method unless you specify a folder in the parameter of this method. It seems that an error should be written for this.
So, when you write your recursive function, you will need to set the default directory once, and then change the directory in the ListDirectory call when you ListDirectory over the folders. The listing lists the SftpFiles. Then they can be checked individually for IsDirectory == true . Just keep in mind that listing also returns entries . and .. (which are directories). You will want to skip them if you want to avoid an infinite loop. :-)
EDIT 2/23/2018
I looked through some of my old answers and would like to apologize for the answer above and provide the following working code. Note that this example does not require ChangeDirectory , since it uses Fullname for ListDirectory :
void Main() { using (var client = new Renci.SshNet.SftpClient("sftp.host.com", "user", "password")) { var files = new List<String>(); client.Connect(); ListDirectory(client, ".", ref files); client.Disconnect(); files.Dump(); } } void ListDirectory(SftpClient client, String dirName, ref List<String> files) { foreach (var entry in client.ListDirectory(dirName)) { if (entry.IsDirectory) { ListDirectory(client, entry.FullName, ref files); } else { files.Add(entry.FullName); } } }