Extracting file names from WebRequestMethods.Ftp.ListDirectoryDetails
Asked Answered
T

3

7

I have an application that does the following: directory listing, download file, download all.

I have an issue with getting the file names from WebRequestMethods.Ftp.ListDirectoryDetails. It seems that it is not possible to do so for every scenario.

WebRequestMethods.Ftp.ListDirectoryDetails returns a lineItem in the following manner:

"-rw-r--r-- 1 ftp ftp 39979 Aug 01 16:02 db to pc 2014-08-05 07-30-00.csv"

I am using the first character to determine if it is a file or directory. Then I split the file on space and get the file name after a fixed index amount within the split. The issue in my implementation is that if a file has multiple spaces then it would be incorrectly referenced with less spaces and the file would not be found when attempting to download it.

I am not able use the split.last() since a file name can have spaces nor WebRequestMethods.Ftp.ListDirectory since it does not allow us to distinguish between a Directory and a file without an extension. Nor a regex since a file name can have a date in it. Any assistance in finding a solution that completely covers all cases would be great.

bool isDirectory = line.Substring(0,1).Equals("d", System.StringComparison.OrdinalIgnoreCase);

string[] itemNames = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries).Select((value, index) => new { value, index }).Where(i => i.index > 7).Select(i => i.value).ToArray();
string val = string.Join(" ", itemNames);
Tetrameter answered 11/8, 2014 at 15:3 Comment(0)
T
14

The final solution was to use regex and split it using groups. This resolved all issues and allowed me to get the file / directory name and whether it was a directory or file.

string regex =
@"^" +                          //# Start of line
@"(?<dir>[\-ld])" +             //# File size          
@"(?<permission>[\-rwx]{9})" +  //# Whitespace          \n
@"\s+" +                        //# Whitespace          \n
@"(?<filecode>\d+)" +
@"\s+" +                        //# Whitespace          \n
@"(?<owner>\w+)" +
@"\s+" +                        //# Whitespace          \n
@"(?<group>\w+)" +
@"\s+" +                        //# Whitespace          \n
@"(?<size>\d+)" +
@"\s+" +                        //# Whitespace          \n
@"(?<month>\w{3})" +            //# Month (3 letters)   \n
@"\s+" +                        //# Whitespace          \n
@"(?<day>\d{1,2})" +            //# Day (1 or 2 digits) \n
@"\s+" +                        //# Whitespace          \n
@"(?<timeyear>[\d:]{4,5})" +    //# Time or year        \n
@"\s+" +                        //# Whitespace          \n
@"(?<filename>(.*))" +          //# Filename            \n
@"$";                           //# End of line


var split = new Regex(regex).Match(line);
string dir = split.Groups["dir"].ToString();
string filename = split.Groups["filename"].ToString();
bool isDirectory = !string.IsNullOrWhiteSpace(dir) && dir.Equals("d", StringComparison.OrdinalIgnoreCase);

Thanks to: http://blogs.msdn.com/b/adarshk/archive/2004/09/15/sample-code-for-parsing-ftpwebrequest-response-for-listdirectorydetails.aspx for providing the regex.

Tetrameter answered 14/8, 2014 at 8:58 Comment(1)
I can't get permission details by using WebRequestMethods.Ftp.ListDirectoryDetails. Do I need to provide permission to get permission details of file/folder. Kindly assist.Livesay
P
5

Simpler solution could be:

isDirectory=line[0]=='d'; 
filename = line.Split(new char[] {' '}, 9,StringSplitOptions.RemoveEmptyEntries)[8]
Priceless answered 8/1, 2015 at 8:31 Comment(1)
this is awesome. Short and simple. Thank you for that.Noma
D
0

Based on Sasa's suggestion, the following code can be used to get a list of files.

List<string> availableFiles = new List<string>();
string line = string.Empty;

ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse())
{
    using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
    {
        line = streamReader.ReadLine();
        while (!string.IsNullOrEmpty(line))
        {
            if (line[0] != 'd')
            {
                availableFiles.Add(line.Split(new char[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries)[8]);
            }

            line = streamReader.ReadLine();
        }
    }
}
Dukes answered 13/1, 2017 at 14:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.