2012-11-26 16 views
6

SFTP'yi kullanarak dosya ve dizinlerin listesini bir liste olarak almak için Renci.SshNet kütüphanesini kullanıyorum. SFTP sitesini bağlayabiliyorum ama C# 'de yinelenen dizinler ve dosyalar listesini nasıl alacağımı bilmiyorum. Hiçbir yararlı örnek bulamadım.SshNet SFTP Dosya ve Dizinleri Alın

Bunu deneyen var mı? Eğer öyleyse, bu dosyaları ve klasörleri tekrar tekrar nasıl elde edeceğiniz hakkında bazı örnek kodlar gönderebilirsiniz.

sayesinde prav

cevap

2

bu deneyin: beklediğiniz olabileceğinden ChangeDirectory ve ListDirectory arasındaki etkileşim işe yaramaz çünkü

var filePaths = client.ListDirectory(client.WorkingDirectory); 
9

Bu kütüphane bu özyinelemeli listeleme zor kılan bazı tuhaflıklar vardır.

şu değil listesine/home dizinindeki dosyaları yapar bunun yerine/(root) dosyaları listeler dizini:

sftp.ChangeDirectory("home"); 
sftp.ListDirectory("").Select (s => s.FullName); 

gelmez aşağıdaki değil eser ve SftpPathNotFoundException döndürür:

sftp.ChangeDirectory("home"); 
sftp.ListDirectory("home").Select (s => s.FullName); 

aşağıdaki/home dizinindeki dosyaları listelemek için doğru yoldur

sftp.ChangeDirectory("/"); 
sftp.ListDirectory("home").Select (s => s.FullName); 

Bana sorarsan bu çok çılgın. Varsayılan yöntemin ChangeDirectory yöntemiyle ayarlanması, bu yöntemin parametresinde bir klasör belirtmedikçe, ListDirectory yönteminde bir etki yaratmaz. Bunun için bir böcek yazılmalı gibi görünüyor.

Bu nedenle, özyinelemeli işlevinizi yazdığınızda, varsayılan dizini bir kez ayarlamanız ve daha sonra klasörler üzerinde yinelediğinizde ListDirectory aralığındaki dizini değiştirmeniz gerekir. Giriş, SftpFiles sayılamaz bir sayı döndürür. Bunlar daha sonra IsDirectory == true için ayrı ayrı kontrol edilebilir. Sadece girişin de . ve .. girişlerini (dizinler) döndürdüğünü unutmayın. Sonsuz bir döngüden kaçınmak istiyorsanız bunları atlamak isteyeceksiniz. :-)

DÜZENLEME 2/23/2018

benim eski bazı yanıtlar incelerken ve üzeri cevap için özür ve aşağıdaki çalışma kodu arz etmek istiyorum. o ListDirectory için Fullname kullanıyor çünkü bu örnek, ChangeDirectory gerektirmez unutmayın:

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); 
     } 
    } 
} 
+4

sftp.ListDirectory ("") çalışmıyor, ancak sftp.ListDirectory (".") Hatırlıyor '.' 'geçerli dizin' anlamına gelir. Ancak, ev klasörü için '~' kısayolunu desteklemiyor gibi görünüyor. – Gargravarr

+0

Açıklama için, verilen bir kök klasörden başlayarak tüm dizinlerin ve alt dizinlerin bir listesini veya bir ağacını gerçekte nasıl alacağınıza dair tam bir örnek var mı? Ssh.net'in neden ListDirectory yönteminin kendisinde bir bool yineleme sunmadığını merak ediyorum. Bu günlerde .net için daha iyi bir çözüm var mı? Yani Bu temel görevleri zaten uygulayan özgür olan daha iyi bir lib nedir? Ancak, çalışan bir örnek çok yardımcı olabilir, teşekkürler! – Erik

0

Bunu kullanarak özyinelemeye elde ettik. Oluşturuldu sınıf olarak bir TransportResponse Bu gibi bir

public class TransportResponse 
{ 
    public string directoryName { get; set; } 
    public string fileName { get; set; } 
    public DateTime fileTimeStamp { get; set; } 
    public MemoryStream fileStream { get; set; } 
    public List<TransportResponse> lstTransportResponse { get; set; } 
} 

TransportResponse sınıfının bir listesini oluşturuyorum. directoryName boş değilse, bir MemoryStream olarak bu dizinde içindeki dosyaları (bu kullanımı durumda uyarınca değiştirilebilir) bu yardımcı olur

List<TransportResponse> lstResponse = new List<TransportResponse>(); 
using (var client = new SftpClient(connectionInfo)) 
    { 
      try 
      { 
        Console.WriteLine("Connecting to " + connectionInfo.Host + " ..."); 
        client.Connect(); 
        Console.WriteLine("Connected to " + connectionInfo.Host + " ..."); 
      } 
      catch (Exception ex) 
      { 
        Console.WriteLine("Could not connect to "+ connectionInfo.Host +" server. Exception Details: " + ex.Message); 
      } 
      if (client.IsConnected) 
      { 
        var files = client.ListDirectory(transport.SourceFolder); 
        lstResponse = downloadFilesInDirectory(files, client); 
        client.Disconnect(); 
      } 
      else 
      { 
        Console.WriteLine("Could not download files from "+ transport.TransportIdentifier +" because client was not connected."); 
      } 
    } 



private static List<TransportResponse> downloadFilesInDirectory(IEnumerable<SftpFile> files, SftpClient client) 
    { 
     List<TransportResponse> lstResponse = new List<TransportResponse>(); 
     foreach (var file in files) 
     { 
      if (!file.IsDirectory) 
      { 
       if (file.Name != "." && file.Name != "..") 
       { 
        if (!TransportDAL.checkFileExists(file.Name, file.LastWriteTime)) 
        { 
         using (MemoryStream fs = new MemoryStream()) 
         { 
          try 
          { 
           Console.WriteLine("Reading " + file.Name + "..."); 
           client.DownloadFile(file.FullName, fs); 
           fs.Seek(0, SeekOrigin.Begin); 
           lstResponse.Add(new TransportResponse { fileName = file.Name, fileTimeStamp = file.LastWriteTime, fileStream = new MemoryStream(fs.GetBuffer()) }); 
          } 
          catch(Exception ex) 
          { 
           Console.WriteLine("Error reading File. Exception Details: " + ex.Message); 
          } 
         } 
        } 
        else 
        { 
         Console.WriteLine("File was downloaded previously"); 
        } 
       } 
      } 
      else 
      { 
       if (file.Name != "." && file.Name != "..") 
       { 
        lstResponse.Add(new TransportResponse { directoryName = file.Name,lstTransportResponse = downloadFilesInDirectory(client.ListDirectory(file.Name), client) }); 
       }     
      } 
     } 

     return lstResponse; 
    } 

Umut olacak aynı sınıfın bir listesini içerecektir.Teşekkür

0

@Carlos Bos

Bu kütüphane beklediğiniz olabileceğinden ChangeDirectory ve ListDirectory arasındaki etkileşim işe yaramaz çünkü zor bu özyinelemeli girişi yapan bazı tuhaflıklar vardır.

doğru

ChangeDirectory() parametresidir, iyi işlev görür

"" Eğer

SftpClient sftp ...; 
sftp.ChangeDirectory("some_folder"); 
//get file list 
List<SftpFile> fileList = sftp.ListDirectory("some_folder").ToList(); 

yaparsanız ListDirectory() çağrısı "some_folder/some_folder" Ben kullanmak geçici çözüm kaydetmek ve önce geçerli dizini restore etmektir

bekler çünkü

ama sonra bir onaylama işlemi yoktur uzak bir yükleme/"some_folder" için yeniden adlandırma ve operasyondan önce bu klasörü listelemek için gereken

string working_directory = sftp.WorkingDirectory; 
sftp.ChangeDirectory("some_folder"); 
sftp.RenameFile("name", "new_name"); 
sftp.ChangeDirectory(working_directory); 
(örn görmek için dosya zaten var) dosya varsa 0

kontrol etmek, bu çağrı

sftp.Exists(path) 

yeterlidir veya hassas örneğinde olduğu gibi, diğer bazı kriterleri eklemek istediğiniz ya da olmasın

public FileExistence checkFileExists(string folder, string fileName) 
    { 
     //get file list 
     List<SftpFile> fileList = sftp.ListDirectory(folder).ToList(); 

     if (fileList == null) 
     { 
     return FileExistence.UNCONFIRMED; 
     } 

     foreach (SftpFile f in fileList) 
     { 
     Console.WriteLine(f.ToString()); 
     //a not case sensitive comparison is made 
     if (f.IsRegularFile && f.Name.ToLower() == fileName.ToLower()) 
     { 
      return FileExistence.EXISTS; 
     } 
     } 

     //if not found in traversal , it does not exist 
     return FileExistence.DOES_NOT_EXIST; 
    } 

eğer FileExistence

public enum FileExistence 
    { 
     EXISTS, 
     DOES_NOT_EXIST, 
     UNCONFIRMED 
    }; 
olduğu
İlgili konular