Skip to content

Directory Listing

Robin Rodricks edited this page Apr 18, 2023 · 18 revisions

API

  • GetListing() - Get a file listing of the given directory. Add FtpListOption.Recursive to recursively list all the sub-directories as well. Returns one FtpListItem per file or folder with all available properties set. See FtpListOption for the full list of option flags you can pass. Each item contains:

    • Type : The type of the object. (File, Directory or Link)

    • Name : The name of the object. (minus the path)

    • FullName : The full file path of the object. If filenames look wrong, select the correct encoding.

    • Created : The created date/time of the object, converted into the format specified in the timezone configuration. Default: DateTime.MinValue if not provided by server.

    • Modified : The last modified date/time of the object, converted into the format specified in the timezone configuration. If you get incorrect values, try adding the FtpListOption.Modify flag which loads the modified date/time using another MDTM command. Default: DateTime.MinValue if not provided by server.

    • Size : The size of the file in bytes. If you get incorrect values, try adding the FtpListOption.Size flag which loads the file size using another SIZE command. Default: 0 if not provided by server.

    • LinkTarget : The full file path the link points to. Only filled for symbolic links.

    • LinkObject : The file/folder the link points to. Only filled for symbolic links if FtpListOption.DerefLink flag is used.

    • SpecialPermissions : Gets special permissions such as Stiky, SUID and SGID.

    • Chmod : The CHMOD permissions of the object. For example 644 or 755. Default: 0 if not provided by server.

    • OwnerPermissions : User rights. Any combination of 'r', 'w', 'x' (using the FtpPermission enum). Default: FtpPermission.None if not provided by server.

    • GroupPermissions : Group rights. Any combination of 'r', 'w', 'x' (using the FtpPermission enum). Default: FtpPermission.None if not provided by server.

    • OtherPermissions : Other rights. Any combination of 'r', 'w', 'x' (using the FtpPermission enum). Default: FtpPermission.None if not provided by server.

    • RawPermissions : The raw permissions string received for this object. Use this if other permission properties are blank or invalid.

    • Input : The raw string that the server returned for this object. Helps debug if the above properties have been correctly parsed.

  • GetNameListing() - A simple command that only returns the list of file paths in the given directory, using the NLST command.

  • GetObjectInfo() - Get information for a single file or directory as an FtpListItem. It includes the type, date created, date modified, file size, permissions/chmod and link target (if any).

Settings

  • Config.ListingParser - File listing parser to be used. Automatically calculated based on the type of the server, unless changed. Default: FtpParser.Auto. If you want to override this property, make sure to do it after calling Connect.

  • Config.ListingCustomParser - Custom file listing parser method to be used. Automatically switches ListingParser to FtpParser.Custom when set. Default: null.

  • Config.ListingCulture - Culture used to parse file listings. Default: CultureInfo.InvariantCulture.

  • Config.ListingDataType - Download file listings in ASCII or Binary mode? Default: FtpDataType.Binary.

  • Config.BulkListing - If true, increases performance of GetListing by reading multiple lines of the file listing at once. If false then GetListing will read file listings line-by-line. If GetListing is having issues with your server, set it to false. Default: true.

  • Config.BulkListingLength - Bytes to read during GetListing. Only honored if BulkListing is true. Default: 128.

  • RecursiveList - Uses predefined logic to check if your server supports a recursive LIST command. Set this to true if you are sure your server supports recursive listing. (LIST -R).

Examples

C#

VB.NET

How does GetListing() work internally?

  1. When you call GetListing(), FluentFTP first attempts to use machine listings (MLSD command) if they are supported by the server. These are most accurate and you can expect correct file size and modification date (UTC). You may also force this mode using client.ListingParser = FtpParser.Machine, and disable it with the FtpListOption.ForceList flag. You should also include the FtpListOption.Modify flag for the most accurate modification dates (down to the second).

  2. If machine listings are not supported we fallback to the appropriate OS-specific parser (LIST command), listed below. You may force usage of a specific parser using client.ListingParser = FtpParser.*.

    • Unix parser : Works for Pure-FTPd, ProFTPD, vsftpd, etc. If you encounter errors you can always try the alternate Unix parser using client.ListingParser = FtpParser.UnixAlt.

    • Windows parser : Works for IIS, DOS, Azure, FileZilla Server, etc.

    • VMS parser : Works for Vax, VMS, OpenVMS, etc.

    • NonStop parser : Works for Tandem, HP NonStop Guardian, etc.

    • IBM parser : Works for IBM OS/400, etc.

  3. And if none of these satisfy you, you can fallback to name listings (NLST command), which are much slower than either LIST or MLSD. This is because NLST only sends a list of filenames, without any properties. The server has to be queried for the file size, modification date, and type (file/folder) on a file-by-file basis. Name listings can be forced using the FtpListOption.ForceNameList flag.

Note: Some FTP servers return no answer when listing an empty folder, so the client has no socket on the other side to communicate with. These exceptions are internally caught and an empty file listing is returned. If you need to check the implementation of this, search for all instances of FtpMissingSocketException in the FluentFTP project.

How does GetListing() return a recursive file listing?

In older versions of FluentFTP, we assumed that all servers supported recursive listings via the LIST -R command. However this caused numerous issues with various FTP servers that did not support recursive listings: The GetListing() call would simply return the contents of the first directory without any of the child directories included.

Therefore, since version 20.0.0, we try to detect the FTP server software and if we determine that it does not support recursive listing, we do our own manual recursion. We begin by assuming that all servers do not support recursive listing, and then whitelist specific server types.

If you feel that GetListing() is too slow when using recursive listings, and you know that your FTP server software supports the LIST -R command, then please contribute support for your server:

  1. Locate your FTP server type exists in the FtpServer enum.

  2. Update FtpClient.RecursiveList() to return true for your server type.

Can I filter file listings using wildcards?

Yes, if your FTP server supports it.

I would like to chime in here, if I may.

Different FTP (RFC 959) server implementations have taken various liberties in implementing wildcards, and to which degree. The wildcard functionality that you can achieve today, currently depends entirely on the server that you are connecting to.

Here is an example, using an up-to-date ProFTPD server and the MSLD FTP command.

client.Connect();
var item = client.GetListing("*.bin");
client.Disconnect();

FTP logs:

...
Command:  PWD
Response: 257 "/home/mike" is the current directory [<1ms]
>         GetListing("*.bin", Auto)
Command:  PASV
Status:   Waiting for response to: PASV
Response: 227 Entering Passive Mode (192,168,1,109,154,73). [1ms]
Status:   Connecting to IP #1= ***:39497
Command:  MLSD /home/mike/*.bin
Response: 550 /home/mike/*.bin: No such file or directory [<1ms]
...

As you can see, on ProFTPD, MLSD with wildcards is rejected.

But:

But if you code this which executes the LIST FTP command:

var item = client.GetListing("*.bin", FtpListOption.ForceList);

you will get:

...
Command:  LIST /home/mike/*.bin
Response: 150 Opening BINARY mode data connection for file list [<1ms]
+---------------------------------------+
Listing:  -rw-r--r--   1 mike     mike            6 Sep 18  2022 /home/mike/test.bin
-----------------------------------------

and the list items are populated correctly.

Wildcards work, when the server supports them. You just need to find the right way to code it, and do some experiments to see what works and what does not.

Clone this wiki locally