20

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.

I would like to be able to have a function (let's call it readglob) that takes a string and returns a vector of strings, each containing a filename.

This way, if I have files a.txt b.txt c.txt in my directory and readglob gets an argument *.txt, it returns the above filelist.

//Prototype of this hypothetical function.
vector<string> readglob(string);

Does such exist?

Paul Nathan
  • 39,638
  • 28
  • 112
  • 212

5 Answers5

27

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.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
4

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);
Evan Teran
  • 87,561
  • 32
  • 179
  • 238
A.J.
  • 1,550
  • 2
  • 14
  • 18
2

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

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • That's a bummer. Doing a quick test using cl & #including afx.h results in an link error relating to new. +1 for the link, but I don't want to eat up my evening working on making MFC work for me. – Paul Nathan Aug 13 '09 at 00:55
  • Seems that for non-MFC stuff, you can use FindFirstFile and friends to do it with straight win32 code. – Evan Teran Aug 13 '09 at 00:58
  • MFC is mostly wrappers around win32 calls, couldn't remember the FindFirstFile(), it all comes back to me now. – Martin Beckett Aug 13 '09 at 01:31
1

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...

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
0

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.

Roboprog
  • 3,054
  • 2
  • 28
  • 27
  • According to http://stackoverflow.com/questions/883594/microsoft-visual-studio-opendir-and-readdir-how opendir/readir aren't in Visual Studio. – Paul Nathan Aug 13 '09 at 00:52
  • Drat! those must be POSIX, not ANSI. Whatever happened to the Win NT POSIX layer??? – Roboprog Aug 13 '09 at 12:12