More .NET components

Directory operations

Working with current directory #

To get current directory, use GetCurrentDirectory method. To change it, use ChangeDirectory method.

CSharp

// set current directory
ftp.ChangeDirectory("/MyData");

// display the current directory to the user
string currentDir = ftp.GetCurrentDirectory();
Console.WriteLine("Current directory changed to: {0}", currentDir);

VisualBasic

' set current directory
ftp.ChangeDirectory("/MyData")

' display the current directory to the user
Dim currentDir As String = ftp.GetCurrentDirectory()
Console.WriteLine("Current directory changed to: {0}", currentDir)

Listing directory content #

To retrieve listings of directory content, three methods are available:

  • GetList - returns collection of FtpItem objects
  • GetNameList - returns a String array of item names
  • GetRawList - returns a String array of item information in server-specific format (see more)

All these methods accept an optional argument which represents a path and/or a mask (wildcard pattern). Please note that the argument is processed by the FTP server and some servers don't support it. To make your code compatible with those, consider calling ChangeDirectory first to select the target directory and then call the argument-less variant of a Get*List method.

CSharp

// get items within the current directory
FtpItemCollection currentItems = ftp.GetList();

// get names of items within "/MyData
string[] dataItems = ftp.GetNameList("/MyData");

// get server-specific listing of all ".txt" files in "/MyData"
string[] dataTextFiles = ftp.GetRawList("/MyData/*.txt");

VisualBasic

' get items within the current directory
Dim currentItems As FtpItemCollection = ftp.GetList()

' get names of items within "/MyData
Dim dataItems As String() = ftp.GetNameList("/MyData")

' get server-specific listing of all ".txt" files in "/MyData"
Dim dataTextFiles As String() = ftp.GetRawList("/MyData/*.txt")
Tip: To retrieve listing of items in subdirectories as well, use a more powerful GetItems method.
See comparison of Get*List and GetItems methods.

Listing directory content - recursively #

To retrieve a listing of directory content including items in subdirectories, or to use more complex filtering criteria, use GetItems method.

Tip: For more information on wildcards, traversal modes and file sets, see wildcards and TraversalMode and Rebex.IO.FileSet features.

CSharp

FtpItemCollection items;

// get all items of current directory recursively
// (items from subdirectories are returned as well)
items = ftp.GetItems("*");

// get all ".txt" files of "/MyData" directory only
// (files from subdirectories are not returned)
items = ftp.GetItems("/MyData/*.txt", TraversalMode.MatchFilesShallow);

// get all ".txt" files under "/MyData" directory
// (files from subdirectories are returned as well)
items = ftp.GetItems("/MyData/*.txt", TraversalMode.MatchFilesDeep);

// initialize a file set
var fileSet = new Rebex.IO.FileSet("/MyData");
fileSet.Include("Web");
fileSet.Exclude("Web/Images");

// get all items defined by the file set
items = ftp.GetItems(fileSet);

VisualBasic

Dim items As FtpItemCollection

' get all items of current directory recursively
' (items from subdirectories are returned as well)
items = ftp.GetItems("*")

' get all ".txt" files of "/MyData" directory only
' (files from subdirectories are not returned)
items = ftp.GetItems("/MyData/*.txt", TraversalMode.MatchFilesShallow)

' get all ".txt" files under "/MyData" directory
' (files from subdirectories are returned as well)
items = ftp.GetItems("/MyData/*.txt", TraversalMode.MatchFilesDeep)

' initialize a file set
Dim fileSet = New Rebex.IO.FileSet("/MyData")
fileSet.Include("Web")
fileSet.Exclude("Web/Images")

' get all items defined by the file set
items = ftp.GetItems(fileSet)
Caution: The GetItems (as well as other multiple files operations) would not work properly on those FTP servers, which cannot resolve existence of files or directories (some mainframe systems etc.).

Listing directory content - on the fly #

All item listing methods raise a ListItemReceived event when an item is received. This is very useful when working with huge directory listings because it makes it possible to display items as they arrive. It also makes it possible to filter item listings using any custom criteria (such as last write time).

Custom item listing filter implementation:

CSharp

void client_ListItemReceived(object sender, FtpListItemReceivedEventArgs e)
{
    // ignore ale items older than 7 days
    if (e.Item.LastWriteTime < DateTime.Now.Date.AddDays(-7))
        e.Ignore();
}

VisualBasic

Sub client_ListItemReceived(ByVal sender As Object, ByVal e As FtpListItemReceivedEventArgs)
    ' ignore ale items older than 7 days
    If e.Item.LastWriteTime < DateTime.Now.Date.AddDays(-7) Then
        e.Ignore()
    End If
End Sub

Registering the event handler:

CSharp

// register ListItemReceived event handler which is raised
// when an item description is received from the server
ftp.ListItemReceived += client_ListItemReceived;

// get items of current directory filtered by the event handler
FtpItemCollection items = ftp.GetList();

VisualBasic

' register ListItemReceived event handler which is raised
' when an item description is received from the server
AddHandler ftp.ListItemReceived, AddressOf client_ListItemReceived

' get items of current directory filtered by the event handler
Dim items As FtpItemCollection = ftp.GetList()

Getting raw directory listing #

The GetRawList method provides a list of files and directories in a server-specific text format.
The format strongly depends on the FTP server:

Sample raw list from the Microsoft IIS FTP server:

06-21-13  10:48AM                   17 file.pdf
06-21-13  10:48AM                   17 file.txt
06-21-13  10:48AM       <DIR>          Web

Sample raw list from the Wu-FTPd server:

drwxr-xr-x 2 root root 4096 Aug  3  2012 dir
lrwxrwxrwx 1 root root    8 Aug  3  2012 slink -> test.txt
-rw-r--r-- 2 root root   18 Aug  3  2012 test.txt

Code example

CSharp

// get server-specific listing of items within the current directory
string[] currentItems = ftp.GetRawList();

// get server-specific listing of text files within the specified directory
string[] textFiles = ftp.GetRawList("/MyData/*.txt");

// simply print the directory listing
Console.WriteLine(string.Join("\r\n", currentItems));

VisualBasic

' get server-specific listing of items within the current directory
Dim currentItems As String() = ftp.GetRawList()

' get server-specific listing of text files within the specified directory
Dim textFiles As String() = ftp.GetRawList("/MyData/*.txt")

' simply print the directory listing
Console.WriteLine(String.Join(vbCrLf, currentItems))

Finding files #

To find a file or multiple files on the remote host, use GetList and GetItems methods. The GetList method only searching in one particular folder, while GetItems method can search its subfolders as well:

CSharp

FtpItemCollection items;

// find all "*.txt" files in "/MyData" directory only
items = ftp.GetList("/MyData/*.txt");

// find all "*.txt" files in "/MyData" directory and its subdirectories
items = ftp.GetItems("/MyData/*.txt", TraversalMode.MatchFilesDeep);

VisualBasic

Dim items As FtpItemCollection

' find all "*.txt" files in "/MyData" directory only
items = ftp.GetList("/MyData/*.txt")

' find all "*.txt" files in "/MyData" directory and its subdirectories
items = ftp.GetItems("/MyData/*.txt", TraversalMode.MatchFilesDeep)

Each of these approaches has its pitfalls:

  • GetList method's argument processing is server specific. Use wildcards in GetList method only if you are sure your FTP server supports it well.
  • GetItems method's filtering is performed on client side. When searching even a single file in a large directory hierarchy, a significant amount of time should be considered for loading the directory structure.
  • GetItems method (just like other multiple files operations) won't work properly on FTP servers that don't present a Unix-like filesystem (such as some mainframe systems).

Creating a directory #

To create a new remote directory, use CreateDirectory method. On well-behaved FTP servers, the it returns the absolute path of the newly created directory.

CSharp

// create new remote directory
string newDir = ftp.CreateDirectory("/MyData/Exports");

// diplay the result
Console.WriteLine("New directory created: {0}", newDir);

VisualBasic

' create new directory
Dim newDir As String = ftp.CreateDirectory("/MyData/Exports")

' display the result
Console.WriteLine("New directory created: {0}", newDir)

Deleting a directory #

To delete an empty remote directory, use RemoveDirectory method.

Tip: To delete non-empty directories, use Delete method instead.

CSharp

// delete remote directory if it doesn't exist locally
if (!Directory.Exists(@"C:\MyData\Exports"))
{
    // fails if not empty
    ftp.RemoveDirectory("/MyData/Exports");

    // notify the user
    // ...
}

VisualBasic

' delete remote directory if it doesn't exist locally
If Not Directory.Exists("C:\MyData\Exports") Then
    ' fails if not empty
    ftp.RemoveDirectory("/MyData/Exports")

    ' notify the user
    ' ...
End If

Deleting directories recursively #

To delete non-empty remote directory or multiple files, use Delete method. Be careful - this is a very powerful method.

CSharp

// delete whole remote directory
// (deletes "/MyData/Temp" directory itself as well)
ftp.Delete("/MyData/Temp", TraversalMode.Recursive);

// delete content of remote directory
// (keep "/MyData" directory itself)
ftp.Delete("/MyData/*", TraversalMode.Recursive);

// delete all ".txt" files in "/MyData"
ftp.Delete("/MyData/*.txt", TraversalMode.MatchFilesShallow);

VisualBasic

' delete whole remote directory
' (deletes "/MyData/Temp" directory itself as well)
ftp.Delete("/MyData/Temp", TraversalMode.Recursive)

' delete content of remote directory
' (keep "/MyData" directory itself)
ftp.Delete("/MyData/*", TraversalMode.Recursive)

' delete all ".txt" files in "/MyData"
ftp.Delete("/MyData/*.txt", TraversalMode.MatchFilesShallow)
This method (just like other multiple files operations) won't work properly on FTP servers that don't present a Unix-like filesystem (such as some mainframe systems).

Renaming/moving a directory #

To rename a directory, use Rename method. It can be used for moving a remote directory to another location at the server as well.

CSharp

// rename a remote directory
ftp.Rename("/MyData/A", "/MyData/B");

// move a remote directory
ftp.Rename("/MyData/Exports", "/Backups/Exports");

VisualBasic

' rename a remote directory
ftp.Rename("/MyData/A", "/MyData/B")

' move a remote directory
ftp.Rename("/MyData/Exports", "/Backups/Exports")

Tip: For moving directories between a client and a server, use Upload or Download methods with TransferMethod.Move argument.

Checking directory existence #

To check whether a remote directory already exists, use DirectoryExists method.

CSharp

// check whether a remote directory exists
bool exists = ftp.DirectoryExists("/MyData/Exports");

if (exists)
{
    // prompt the user
    // ...
}

VisualBasic

' check whether a remote directory exists
Dim exists = ftp.DirectoryExists("/MyData/Exports")

If exists Then
    ' prompt the user
    ' ...
End If
Please be aware that this operation is not a part of the original FTP protocol. Although DirectoryExists tries several ways to check whether the file exists and works well with almost all FTP servers, it may fail on some legacy FTP servers with a "not supported" exception.

Sorting directory content #

GetList and GetItems methods return directory items in the same order as returned by the server, which often means no sorting at all. To sort the items, use FtpItemCollection's Sort method and FileSystemItemComparer object.

For more sorting options, see FileSystemItemComparerType enum.

CSharp

// get items in the current directory
FtpItemCollection items = ftp.GetList();

// example 1: large files first
items.Sort(new FileSystemItemComparer(FileSystemItemComparerType.Length));

// example 2: order by multiple fields
// (directories first, then order by file name)
items.Sort(new MultiComparer(
        new FileSystemItemComparer(FileSystemItemComparerType.FileType),
        new FileSystemItemComparer(FileSystemItemComparerType.Name)));

VisualBasic

' get items in the current directory
Dim items As FtpItemCollection = ftp.GetList()

' example 1: large files first
items.Sort(New FileSystemItemComparer(FileSystemItemComparerType.Length))

' example 2: order by multiple fields
' (directories first, then order by file name)
items.Sort(New MultiComparer(
        New FileSystemItemComparer(FileSystemItemComparerType.FileType),
        New FileSystemItemComparer(FileSystemItemComparerType.Name)))

LINQ support - IEnumerable<T> collection #

The FtpItemCollection object returned by GetList and GetItems methods implements IEnumerable<FtpItem> to support LINQ queries:

As it implements IEnumerable<FileSystemItem> as well (part of common FTP and FTP API), casting it explicitly to IEnumerable<FtpItem> might be necessary in order to use the proper LINQ extension methods. You can achieve this by calling Cast<FtpItem> method.

CSharp

DateTime dt = DateTime.Now.Date.AddDays(-7);

// get all ".txt" files not older than 7 days sorted by path
// from current directory using LINQ
var files1 =
    ftp.GetList("*.txt").Cast<FtpItem>().
    Where(item => item.IsFile && item.LastWriteTime > dt).
    OrderBy(item => item.Path);

// get all ".txt" files not older than 7 days sorted by path
// anywhere under current directory using LINQ to SQL
var items = ftp.GetItems("*.txt", TraversalMode.MatchFilesDeep);
var files2 =
    from FtpItem item in items
    where item.IsFile && item.LastWriteTime > dt
    orderby item.Path
    select item;

VisualBasic

Dim dt = DateTime.Now.Date.AddDays(-7)

' get all ".txt" files not older than 7 days sorted by path
' from current directory using LINQ
Dim files1 =
    ftp.GetList("*.txt").Cast(Of FtpItem).
    Where(Function(item) item.IsFile AndAlso item.LastWriteTime > dt).
    OrderBy(Function(item) item.Path)

' get all ".txt" files not older than 7 days sorted by path
' anywhere under current directory using LINQ to SQL
Dim items = ftp.GetItems("*.txt", TraversalMode.MatchFilesDeep)
Dim files2 =
    From item As FtpItem In items
    Where item.IsFile AndAlso item.LastWriteTime > dt
    Order By item.Path
    Select item

Powerful directory listing parser #

The original FTP protocol defined no standard directory listing format. Although most modern FTP servers support a MLST format intended for machine processing, there are many FTP servers still in use that only support a human-readable listing format (see examples). Fortunately, Rebex FTP/SSL features a powerful listing parser that can parse almost all the various listing formats into a collection of well structured FtpItem objects, making the name, size, modified time or type accessible as strongly-typed properties.

See a list of directory listing formats supported by the built-in parser.

Custom directory listing parsers #

If you encounter an FTP server with a rare listing format not supported by Rebex parsers, you can easily add a parser for it:

CSharp

// sample of custom directory item parser method
private static void MyDirectoryItemParser(object sender, FtpItemParseEventArgs e)
{
    // if the item has a valid name, return the original item
    if (e.Item != null || !string.IsNullOrEmpty(e.Item.Name))
        return;

    // a very simple sample of parsing item from the raw list
    string parsedName = e.RawLine.Substring(39);
    bool parsedDirectory = e.RawLine.Contains("<DIR>");

    // create a new item and fill it with parsed values
    e.Item = new FtpItem(
                    parsedName,
                    0,
                    parsedDirectory ? FtpItemType.Directory : FtpItemType.File);
}

VisualBasic

' sample of custom directory item parser method
Private Sub MyDirectoryItemParser(ByVal sender As Object,
                                ByVal e As FtpItemParseEventArgs)
    ' if the item has a valid name, return the original item
    If Not e.Item Is Nothing And Not String.IsNullOrEmpty(e.Item.Name) Then
        Return
    End If

    ' a very simple sample of parsing item from the raw list
    Dim parsedName = e.RawLine.Substring(39)
    Dim parsedType = FtpItemType.File
    If e.RawLine.Contains("<DIR>") Then
        parsedType = FtpItemType.Directory
    End If

    ' create a new item and fill it with parsed values
    e.Item = New FtpItem(parsedName, 0, parsedType)
End Sub

Register the parser as a static event handler:

CSharp

// register the custom parser to the FtpItem class
FtpItem.ItemParse += new FtpItemParseEventHandler(MyDirectoryItemParser);

// get the directory listing using the new parser
foreach (var item in ftp.GetList())
    Console.WriteLine("{0} {1}", item.Name, item.IsDirectory ? " <dir>" : "");

VisualBasic

' register the custom parser to the FtpItem class
AddHandler FtpItem.ItemParse, New FtpItemParseEventHandler(AddressOf MyDirectoryItemParser)

' get the directory listing using the new parser
For Each item In ftp.GetList()
    Console.WriteLine("{0} dir={1}", item.Name, item.IsDirectory)
Next