#c #linux #string #vector #absolute-path
#c #linux #строка #вектор #абсолютный путь
Вопрос:
Текущий фрагмент кода будет соответствовать шаблону и перечислит все соответствующие файлы шаблонов, присутствующие в каталоге, указанном где в приведенном ниже примере файла является шаблоном, который должен быть сопоставлен *, здесь вывод будет указан с абсолютным путем, как показано ниже.
/home/downloads/File1
/home/downloads/File2
/home/downloads/File3
/home/downloads/File4
при этом я ищу только имя файла, которое должно быть указано, например, как указано ниже:
File1
File2
File3
File4
код c ниже:
#include <glob.h>
#include <cerrno>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
using namespace std;
vector<string> glob(const stringamp; pattern) {
glob_t glob_result = {0}; // zero initialize
// do the glob operation
int return_value = ::glob(pattern.c_str(), GLOB_TILDE, NULL, amp;glob_result);
if(return_value != 0) throw runtime_error(strerror(errno));
// collect all the filenames into a std::vector<std::string>
// using the vector constructor that takes two iterators
vector<string> filenames(
glob_result.gl_pathv, glob_result.gl_pathv glob_result.gl_pathc);
// cleanup
globfree(amp;glob_result);
// done
return filenames;
}
int main() {
try { // catch exceptions
vector<string> res = glob("/home/downloads/File*"); // files with an "File" in the filename
for(size_t i = 0; i< res.size(); i)
std::cout << res[i] << 'n';
} catch(const exceptionamp; ex) {
cerr << ex.what() << endl;
}
}
Ответ №1:
Вроде как вы можете отфильтровывать каталоги. Измените GLOB_TILDE
GLOB_TILDE | GLOB_MARK
примерно так:
vector<string> glob(const stringamp; pattern) {
glob_t glob_result = {};
vector<string> filenames;
try {
int return_value = ::glob(pattern.c_str(), GLOB_TILDE | GLOB_MARK, NULL, amp;glob_result);
if (return_value != 0) {
throw runtime_error(strerror(errno));
}
filenames.reserve(glob_result.gl_pathc);
for (size_t globIndex = 0; globIndex < glob_result.gl_pathc; globIndex) {
std::string filename = glob_result.gl_pathv[globIndex];
if (filename.size() > 0 amp;amp; filename[filename.size() - 1] != '/') {
filenames.push_back(filename);
}
}
} catch(...) {
globfree(amp;glob_result);
throw;
}
// cleanup
globfree(amp;glob_result);
// done
filenames.shrink_to_fit();
return filenames;
}
Примечания:
- вам все равно придется
stat
просматривать каждый результат и проверять, является ли он файлом. Может быть символической ссылкой, файлом устройства, именованным каналом (FIFO)… - код не был безопасным для исключений, при заполнении вектора память может закончиться, и ваша очистка не произойдет. Используйте try / catch или что-то вроде scope_exit (если можете) или напишите объект guard и используйте его деструктор.
- Я не уверен, следует ли вам
globfree
в случае ошибки, но valgrind предполагает, что это не проблема.