Is there a smooth way to glob in C or C++ in Windows?
E.g., myprogram.exe *.txt sends my program an ARGV list that has...ARGV[1]=*.txt
in it.
Ehw. I had to implement something like this in ANSI C about 15 years ago. Start with the ANSI opendir/readdir routines, I guess. Globs aren't exactly RegExs, so you will have to implement your own filtering.
This is very Windows-specific. I don't know how you'd write this to be cross-platform. But I've used this in Windows programs and it works well for me.
// Change to the specified working directory
string path;
cout << "Enter the path to report: ";
cin >> path;
_chdir(path.c_str());
// Get the file description
string desc;
cout << "Enter the file description: ";
cin >> desc;
// List the files in the directory
intptr_t file;
_finddata_t filedata;
file = _findfirst(desc.c_str(),&filedata);
if (file != -1)
{
do
{
cout << filedata.name << endl;
// Or put the file name in a vector here
} while (_findnext(file,&filedata) == 0);
}
else
{
cout << "No described files found" << endl;
}
_findclose(file);
Link with setargv.obj
(or wsetargv.obj
) and argv[] will be globbed for you similar to how the Unix shells do it:
I can't vouch for how well it does it though.
there was talk about having it in Boost::filesystem but it was dropped in favor of using the boost::regex.
For win32 specific (MFC) you can use the CFileFind class
There may be a better way now, but last time I had to deal with this problem I ended up including Henry Spencer's regex library statically linked into my program (his library is BSD licensed), and then I made a wrapper class that converted the user's glob-expressions into regular expressions to feed to the regex code. You can view/grab the wrapper class here if you like.
Once you have those parts in place, the final thing to do is actually read the directory, and pass each entry name into the matching function to see if it matches the expression or not. The filenames that match, you add to your vector; the ones that don't you discard. Reading the directory is fairly straightforward to do using the DOS _findfirst() and _findnext() functions, but if you want a nicer C++ interface I have a portable wrapper class for that also...