I'm trying to generate a list of files matching a certain file mask and Indy falls over with this error
EidReplyRFCError with message '.': No such file or directory.
I've tried several variations and this is the result:
FTP.List( aFiles, '', true );
=> this works
FTP.List( aFiles, '*.*', false );
=> this works too
FTP.List( aFiles, '*.*', true );
=> this fails
FTP.List( aFiles, '*.zip', true );
=> this fails too (despite it being the example in the latest documentation)
FTP.List( '*.*', false );
=> this works
FTP.List( '*.*', true );
=> this fails
I'm using Delphi XE5 & Indy version 10.6. The same issue exists in XE8 if relevant.
Maybe the functionality has changed and the documentation is now wrong or it's a bug in Indy?
I need the "details" so I can compare timestamps & sizes too.
This is not a bug in
TIdFTP
. It is more an omission in the Indy documentation.EIdReplyRFCError
means the FTP server itself is reporting an error in response to the command thatTIdFTP.List()
is sending. Depending on the values of theADetails
parameter andTIdFTP
'sUseMLIS
+CanUseMLS
properties,List()
can send one of three different commands:Thus:
Note that all of the commands that "fail" have something in common - they might be sending an
MLSD ASpecifier
command.Per RFC 959, which defines the
LIST
andNLST
commands:Per RFC 3659, which defines the
MLSD
command:*.*
and*.zip
are not directory names, thus the server will fail ifTIdFTP.List()
sends anMLSD *.*
orMLSD *.zip
command. So it stands to reason thatTIdFTP.UseMLIS
andTIdFTP.CanUseMLS
are likely both True in your case (UseMLIS
is True by default, andCanUseMLS
is commonly True on modern FTP servers).The
MLSD
command does not support server-side filtering like theLIST
/NLST
commands do. So you cannot use things like*.*
and*.zip
withMLSD
. You would have to retrieve the full directory listing and then ignore any entries that you are not interested in. Otherwise, setTIdFTP.UseMLIS
to False before callingTIdFTP.List()
, but then you run the risk ofTIdFTP.DirectoryListing
incorrectly parsing the directory listing of some servers, as the format used by theLIST
command was never standardized, and there are hundreds of custom formats being used all over the Internet (and whyTIdFTP
in Indy 10 includes dozens of listing parsers whenLIST
is used). UnlikeMLSx
, which has a standardized format (which is why it was introduced in the first place, to replace the shortcomings ofLIST
).Thus, what this all comes down to is - when
TIdFTP.UseMLIS
andTIdFTP.CanUseMLS
are both True,ASpecifier
MUST be blank or a directory, NOT a file mask.The
TIdFTP.List()
documentation does state thatList()
may internally callTIdFTP.ExtListDir()
to send anMLSD
command, but it does not specifically mention this particular restriction on theASpecifier
parameter in that case:The
TIdFTP.ExtListDir()
documentation does state that its input parameter must be a directory name, though:On a side note: the
TIdFTP.DirFormat
property will tell you which listing format was detected afterTIdFTP.DirectoryListing
has parsed the results. Or you can look at theDetails
andUsedMLS
properties ofTListFTP.ListResult
(type-cast it toTIdFTPListResult
to access the properties) to deduce which command was sent byTIdFTP.List()
(if successful).