Ftp Directory Partial Listing with Wildcards

FTP directory partial listing with wildcards

The most recent update to the FTP specification (RFC 3659) explicitly forbids it. From section 2.2.2 of that specification, titled "Wildcarding" (emphasis mine):

For the commands defined in this specification, all pathnames are to
be treated literally. That is, for a pathname given as a parameter to
a command, the file whose name is identical to the pathname given is
implied. No characters from the pathname may be treated as special or
"magic", thus no pattern matching (other than for exact equality)
between the pathname given and the files present in the NVFS of the
server-FTP is permitted.

Clients that desire some form of pattern
matching functionality must obtain a listing of the relevant
directory, or directories, and implement their own file name
selection procedures.

That said, if your server supports it, you could still use the FtpWebRequest class, but you'd have to process the response yourself to handle the list of items, as the .NET classes won't understand your server-specific extensions.

ftp_get() file with partial filename(not a wildcard)

Given the relatively small directory size (100+ from comments above), you should be ok first using ftp_nlist() to list all the files and then searching for and downloading the file you want.

$search = '_' . $trackingId . '.dat';
$searchLen = strlen($search);
$dir = '.'; // example directory
$files = ftp_nlist($connection, $dir);
foreach ($files as $file) {
// check if $file ends with $search
if (strrpos($file, $search) === strlen($file) - $searchLen) {
// found it, download it
ftp_get($connection, 'some/local/file/path', $dir . '/' . $file);
}
}

Better and more future-proof options can be found in Michael Berkowski's comment above...

How many files do you expect to be operating in the directory at any given time? If it is a small number, listing the contents via ftp may work suitably. If it is many thousands of files, you might want to store some sort of text manifest file to read from, or index them in a database.

These do hinge on how and when the files are uploaded to the FTP server though so given we don't know anything about that, I cannot provide any solutions.

how to get only those in an FTP directory by a given name?

With most FTP servers, this will do:

files = ftp.nlst("*rhum*")

(although it is non-standard way).

How to get list of files based on pattern matching using FTP?

In general, there's no other way than the one you know: retrieve list of all files and filter them locally.


But many servers support non-standard/proprietary filtering of the listing.

If you are lucky and your FTP server do support this, you can use a file mask to retrieve only a subset of files. In your case the mask would by usually like ABC*. Most major FTP servers do support * pattern.

FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/ABC*");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
Console.WriteLine(reader.ReadToEnd());

For a partial list of supported patterns of common FTP servers, see my answer to FTP directory partial listing with wildcards.

Listing files on FTP server using PHP glob is not working

PHP glob function does not support URL wrappers:

Note: This function will not work on remote files as the file to be examined must be accessible via the server's filesystem.


The only reliable way is to list files matching a wildcard, is to list all files using PHP FTP functions and filter them locally:

$conn_id = ftp_connect("ftp.example.com") or die("Cannot connect");
ftp_login($conn_id, "username", "password") or die("Cannot login");
ftp_pasv($conn_id, true) or die("Cannot change to passive mode");

$files = ftp_nlist($conn_id, "/path");

foreach ($files as $file)
{
if (preg_match("/\.png$/i", $file))
{
echo "Found $file\n";
}
}

(this is what the glob would do internally anyway, had it supported URL wrappers)


Some (most) FTP servers will allow you to use a wildcard directly:

$conn_id = ftp_connect("ftp.example.com") or die("Cannot connect");
ftp_login($conn_id, "username", "password") or die("Cannot login");
ftp_pasv($conn_id, true) or die("Cannot change to passive mode");

$files = ftp_nlist($conn_id, "/path/*.png");

foreach ($files as $file)
{
echo "Found $file\n";
}

But that's a nonstandard feature (while widely supported).

For details see my answer to FTP directory partial listing with wildcards.

Use Python ftplib ftp.dir() or ftp.retrlines('LIST') to return only files containing a string

In general, there's no other way, than retrieving list of all files and filtering them locally.

See Python: How to get list of file and use wildcard in FTP directory?


But many servers support non-standard/proprietary filtering of the listing.

If you are lucky and your FTP server do support this, you can use a file mask to retrieve only a subset of files. In your case the mask would be a simple * pattern, which is supported by most major FTP servers.

ftp.retrlines('LIST *string*')

For a partial list of supported patterns of common FTP servers, see my answer to FTP directory partial listing with wildcards.



Related Topics



Leave a reply



Submit