我想遍歷與「somefiles * .txt」類似的目錄中的所有文件。 boost :: filesystem是否有內置的東西來做到這一點,或者我需要一個正則表達式或什麼對每個葉()?我可以使用掩碼來迭代Boost中目錄中的文件嗎?
51
A
回答
69
編輯:如評論中所述,以下代碼適用於v3之前版本boost::filesystem
。對於v3,請參閱評論中的建議。
boost::filesystem
沒有通配符搜索,你必須自己篩選文件。
這是一個代碼樣本中提取的目錄與boost::filesystem
的directory_iterator
的內容,並與boost::regex
對其進行篩選:
const std::string target_path("/my/directory/");
const boost::regex my_filter("somefiles.*\.txt");
std::vector<std::string> all_matching_files;
boost::filesystem::directory_iterator end_itr; // Default ctor yields past-the-end
for(boost::filesystem::directory_iterator i(target_path); i != end_itr; ++i)
{
// Skip if not a file
if(!boost::filesystem::is_regular_file(i->status())) continue;
boost::smatch what;
// Skip if no match for V2:
if(!boost::regex_match(i->leaf(), what, my_filter)) continue;
// For V3:
//if(!boost::regex_match(i->path().filename(), what, my_filter)) continue;
// File matches, store it
all_matching_files.push_back(i->leaf());
}
(如果你正在尋找一個現成的使用類型與內建目錄過濾,看看Qt的QDir
。)
1
我相信directory_iterators只會提供目錄中的所有文件。由您根據需要過濾它們。
0
正如在Julien-L的末尾所提到的QDir
正是你想要的。
https://qt-project.org/doc/qt-5.0/qtcore/qdir.html#QDir-3
3
我的解決辦法是基本相同朱利安-L,但封裝在包含文件是更好的使用。使用boost :: filesystem v3實現。我猜這樣的東西沒有直接包含在boost :: filesystem中,因爲它會引入對boost :: regex的依賴。
#include "FilteredDirectoryIterator.h"
std::vector<std::string> all_matching_files;
std::for_each(
FilteredDirectoryIterator("/my/directory","somefiles.*\.txt"),
FilteredDirectoryIterator(),
[&all_matching_files](const FilteredDirectoryIterator::value_type &dirEntry){
all_matching_files.push_back(dirEntry.path());
}
);
選擇使用FilteredRecursiveDirectoryIterator遞歸子目錄搜索:
#include "FilteredDirectoryIterator.h"
std::vector<std::string> all_matching_files;
std::for_each(
FilteredRecursiveDirectoryIterator("/my/directory","somefiles.*\.txt"),
FilteredRecursiveDirectoryIterator(),
[&all_matching_files](const FilteredRecursiveDirectoryIterator::value_type &dirEntry){
all_matching_files.push_back(dirEntry.path());
}
);
FilteredDirectoryIterator.h
#ifndef TOOLS_BOOST_FILESYSTEM_FILTEREDDIRECTORYITERATOR_H_
#define TOOLS_BOOST_FILESYSTEM_FILTEREDDIRECTORYITERATOR_H_
#include "boost/filesystem.hpp"
#include "boost/regex.hpp"
#include <functional>
template <class NonFilteredIterator = boost::filesystem::directory_iterator>
class FilteredDirectoryIteratorTmpl
: public std::iterator<
std::input_iterator_tag, typename NonFilteredIterator::value_type
>
{
private:
typedef std::string string;
typedef boost::filesystem::path path;
typedef
std::function<
bool(const typename NonFilteredIterator::value_type &dirEntry)
>
FilterFunction;
NonFilteredIterator it;
NonFilteredIterator end;
const FilterFunction filter;
public:
FilteredDirectoryIteratorTmpl();
FilteredDirectoryIteratorTmpl(
const path &iteratedDir, const string ®exMask
);
FilteredDirectoryIteratorTmpl(
const path &iteratedDir, const boost::regex &mask
);
FilteredDirectoryIteratorTmpl(
const path &iteratedDir,
const FilterFunction &filter
);
//preincrement
FilteredDirectoryIteratorTmpl<NonFilteredIterator>& operator++() {
for(++it;it!=end && !filter(*it);++it);
return *this;
};
//postincrement
FilteredDirectoryIteratorTmpl<NonFilteredIterator> operator++(int) {
for(++it;it!=end && !filter(*it);++it);
return FilteredDirectoryIteratorTmpl<NonFilteredIterator>(it,filter);
};
const boost::filesystem::directory_entry &operator*() {return *it;};
bool operator!=(const FilteredDirectoryIteratorTmpl<NonFilteredIterator>& other)
{
return it!=other.it;
};
bool operator==(const FilteredDirectoryIteratorTmpl<NonFilteredIterator>& other)
{
return it==other.it;
};
};
typedef
FilteredDirectoryIteratorTmpl<boost::filesystem::directory_iterator>
FilteredDirectoryIterator;
typedef
FilteredDirectoryIteratorTmpl<boost::filesystem::recursive_directory_iterator>
FilteredRecursiveDirectoryIterator;
template <class NonFilteredIterator>
FilteredDirectoryIteratorTmpl<NonFilteredIterator>::FilteredDirectoryIteratorTmpl()
: it(),
filter(
[](const boost::filesystem::directory_entry& /*dirEntry*/){return true;}
)
{
}
template <class NonFilteredIterator>
FilteredDirectoryIteratorTmpl<NonFilteredIterator>::FilteredDirectoryIteratorTmpl(
const path &iteratedDir,const string ®exMask
)
: FilteredDirectoryIteratorTmpl(iteratedDir, boost::regex(regexMask))
{
}
template <class NonFilteredIterator>
FilteredDirectoryIteratorTmpl<NonFilteredIterator>::FilteredDirectoryIteratorTmpl(
const path &iteratedDir,const boost::regex ®exMask
)
: it(NonFilteredIterator(iteratedDir)),
filter(
[regexMask](const boost::filesystem::directory_entry& dirEntry){
using std::endl;
// return false to skip dirEntry if no match
const string filename = dirEntry.path().filename().native();
return boost::regex_match(filename, regexMask);
}
)
{
if (it!=end && !filter(*it)) ++(*this);
}
template <class NonFilteredIterator>
FilteredDirectoryIteratorTmpl<NonFilteredIterator>::FilteredDirectoryIteratorTmpl(
const path &iteratedDir, const FilterFunction &filter
)
: it(NonFilteredIterator(iteratedDir)),
filter(filter)
{
if (it!=end && !filter(*it)) ++(*this);
}
#endif
4
有一個Boost Range Adaptors
方式:
#define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0
#include <boost/filesystem.hpp>
#include <boost/range/adaptors.hpp>
namespace bfs = boost::filesystem;
namespace ba = boost::adaptors;
const std::string target_path("/my/directory/");
const boost::regex my_filter("somefiles.*\.txt");
boost::smatch what;
for (auto &entry: boost::make_iterator_range(bfs::directory_iterator(target_path), {})
| ba::filtered(static_cast<bool (*)(const bfs::path &)>(&bfs::is_regular_file))
| ba::filtered([&](const bfs::path &path){ return boost::regex_match(path.filename().string(), what, my_filter); })
)
{
// There are only files matching defined pattern "somefiles*.txt".
std::cout << entry.path().filename() << std::endl;
}
0
我一直在尋找解決這個早些時候,我想我的解決方案是最簡單的
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/exception/all.hpp>
struct dir_filter_iter
: public boost::iterator_facade<
dir_filter_iter,
boost::filesystem::path,
boost::forward_traversal_tag,
boost::filesystem::path
>
{
using path = boost::filesystem::path;
using impl_type = boost::filesystem::directory_iterator;
dir_filter_iter():impl_(){}
dir_filter_iter(path p, boost::regex rgx):impl_(std::move(p)),rgx_(std::move(rgx)){
namespace bf = boost::filesystem;
if(! bf::is_directory(p)){
BOOST_THROW_EXCEPTION(
boost::enable_error_info(std::domain_error("not a dir"))
<< boost::errinfo_file_name(p.string()));
}
}
private:
friend class boost::iterator_core_access;
bool equal(const dir_filter_iter& that)const{
return this->impl_ == that.impl_;
}
void increment(){
assert(impl_ != impl_type());
for(;;){
++impl_;
if(impl_ == impl_type())
break;
std::string s(impl_->path().string());
if(boost::regex_match(s, rgx_)){
break;
}
}
}
path dereference()const{
assert(impl_ != impl_type());
return *impl_;
}
impl_type impl_;
boost::regex rgx_;
};
struct dir_filter_iter_maker{
using value_type = dir_filter_iter;
explicit dir_filter_iter_maker(boost::regex rgx):rgx_(rgx){}
value_type make()const{
return value_type();
}
value_type make(boost::filesystem::path p)const{
return value_type(std::move(p),rgx_);
}
template<typename... Args>
auto operator()(Args&&... args)->decltype(make(args...)){
return this->make(std::forward<Args>(args)...);
}
private:
boost::regex rgx_;
};
然後,你可以做
dir_filter_iter_maker di_maker(boost::regex(R"_(.*\.hpp)_"));
std::for_each(di_maker(p), di_maker(), [](const bf::path& p){std::cout << p.string() << "\n";});
1
接受的答案沒有編譯我,即使我用i->path().extension()
代替的leaf()
。對我有用的是this website的一個例子。下面的代碼,修改,應用過濾器:
vector<string> results;
filesystem::path filepath(fullpath_to_file);
filesystem::directory_iterator it(filepath);
filesystem::directory_iterator end;
const boost::regex filter("myfilter(capturing group)");
BOOST_FOREACH(filesystem::path const &p, make_pair(it, end))
{
if(is_regular_File(p))
{
match_results<string::const_iterator> what;
if (regex_search(it->path().filename().string(), what, pidFileFilter, match_default))
{
string res = what[1];
results.push_back(res);
}
}
}
我使用Boost版本:1.53.0。
爲什麼我們不只是使用3210而有些正則表達式超出了我的想象。
相關問題
- 1. 我可以使用DoxyGen來記錄ActionScript代碼嗎?
- 2. 我可以在maven中使用distributionmanagement來分發文件目錄嗎?
- 3. 我可以在struts2.0的jsp上的迭代器中使用迭代器嗎?
- 4. 我可以使用在parallel_bulk中讀取文件的迭代器嗎?
- 5. 迭代unix目錄中的文件talend
- 6. 迭代目錄中的特定文件
- 7. 我可以使用FSI來調試我的代碼嗎?
- 8. 我們可以在SWING代碼中使用JAVAFX代碼嗎?
- 9. 在目錄中迭代低谷文件
- 10. 在目錄中迭代大文件集
- 11. 我可以搜索目錄和子目錄的頭文件嗎?
- 12. 我可以用一行代碼創建2個目錄嗎?
- 13. 我可以在GitHub的子目錄中創建README文件嗎?
- 14. 我可以從3目錄深的jar中提取文件嗎?
- 15. 我可以使用for-each在Java中迭代NodeList嗎?
- 16. 我可以使用域掩碼加上傳遞的URI嗎?
- 17. 只通過使用MATLAB的目錄中的文件名迭代
- 18. 我可以使用此代碼登錄使用對話框嗎?
- 19. 迭代並使用目錄中的HTML文件 - python
- 20. 如果使用URL掩碼,我們可以在經典ASP中使用Request.QueryString嗎?
- 21. 我可以使用sharedPreferences文件中的項目填充AlertDialog嗎?
- 22. 我可以使用Resharper 2.0檢查我的項目中的代碼問題嗎?
- 23. 我可以使用requirements.txt文件來處理本地python目錄嗎?
- 24. CodeDom可以將源代碼文件添加到項目中嗎?
- 25. 我可以將2個目錄中的文件集成到一個目錄嗎?
- 26. 我可以使用gitg僅查看一個文件/目錄中的更改嗎?
- 27. 我可以使用.htaccess重定向到目錄中最新的文件嗎?
- 28. 迭代目錄中的文件以查找內容
- 29. Gnuplot;迭代目錄中的文件以打印png
- 30. 我可以使用代碼更改Solr data-config.xml文件嗎?
感謝您的非常完整的答案。其他人的兩個注意事項:1)葉文件系統v3(當前默認)不推薦使用,使用路徑()。文件名(),而不是2)如果過濾標準是擴展(很常見),它更容易使用i->路徑).extension()==「.txt」[例如]比正則表達式 – alfC 2011-11-04 07:01:32
現在不推薦使用leaf()。如果你只是想要文件名,我可以用i-> path()。string()或i-> path()。filename()。string()替換i-> leaf() – Fuzz 2012-06-27 01:33:46
正則表達式中的反斜槓必須轉義''somefiles。* \\。txt「' – 2014-04-26 11:37:25