{"id":184,"date":"2019-01-09T14:14:12","date_gmt":"2019-01-09T22:14:12","guid":{"rendered":"http:\/\/35.243.195.209\/?p=184"},"modified":"2019-01-09T14:14:12","modified_gmt":"2019-01-09T22:14:12","slug":"search-files-under-a-directory-in-c","status":"publish","type":"post","link":"https:\/\/nanzhou.cc\/index.php\/2019\/01\/09\/search-files-under-a-directory-in-c\/","title":{"rendered":"Search Files Under a Directory in C++"},"content":{"rendered":"<h2>Summary<\/h2>\n<p>In this post, I will introduce how to get a vector of files in a directory in C++. Instead of <code>filesystem<\/code> in <a href=\"https:\/\/www.boost.org\/doc\/libs\/1_38_0\/libs\/filesystem\/doc\/index.htm\">boost<\/a> or C++ 17, this method is purely based on C++ 11 and Unix platforms.<\/p>\n<h2>Details<\/h2>\n<p>The following codes are self-explained.<\/p>\n<pre><code class=\"c\">\/\/ safe path join in unix-based system\nstring path_join(const string&amp; p1, const string&amp; p2) {\n    char sep = '\/';\n    string tmp = p1;\n\n    if (p1[p1.size() - 1] != sep) { \/\/ Need to add a\n        tmp += sep;                \/\/ path separator\n        return(tmp + p2);\n    }\n    else\n        return(p1 + p2);\n}\n\n\/\/ make sure files are either directories or files\n\/\/ dfs to get all files\nvoid get_files(const string &amp;dir, vector&lt;string&gt; &amp;all_files) {\n    shared_ptr&lt;DIR&gt; directory_ptr(opendir(dir.c_str()), [](DIR* dir){ dir &amp;&amp; closedir(dir); });\n    struct dirent *dirent_ptr;\n    if (!directory_ptr) {\n        cout &lt;&lt; \"Error opening : \" &lt;&lt; strerror(errno) &lt;&lt; dir &lt;&lt; std::endl;\n        return;\n    }\n\n    while ((dirent_ptr = readdir(directory_ptr.get())) != nullptr) {\n        \/\/ get all the files in a directory, ignoring \"..\" and \".\"\n        if (strcmp(dirent_ptr-&gt;d_name, \".\") != 0 &amp;&amp; strcmp(dirent_ptr-&gt;d_name, \"..\") != 0) {\n            string curr_path = path_join(dir, string(dirent_ptr-&gt;d_name));\n            \/\/ if it is a regular file\n            if (dirent_ptr-&gt;d_type == DT_REG) {\n                all_files.push_back(curr_path);\n            } else { \/\/ a directory\n                get_files(curr_path, all_files);\n            }\n        }\n    }\n}\n<\/code><\/pre>\n<h3>shared_ptr<\/h3>\n<pre><code class=\"c\">shared_ptr&lt;DIR&gt; directory_ptr(opendir(dir.c_str()), [](DIR* dir){ dir &amp;&amp; closedir(dir); });\n<\/code><\/pre>\n<p>I will introduce <code>smart_ptr<\/code> in another post. The syntax here of <code>shared_ptr<\/code> basically passes a initial pointer whose type is <code>DIR<\/code> (a directory stream) and a lambda function which defines how to safely delete the pointer (close the directory stream).<br \/>\nSee <a href=\"https:\/\/linux.die.net\/man\/3\/opendir\">opendir<\/a> and <a href=\"https:\/\/linux.die.net\/man\/3\/closedir\">closedir<\/a>.<\/p>\n<h3>dirent and readdir<\/h3>\n<p>See <a href=\"https:\/\/linux.die.net\/man\/3\/readdir\">readdir<\/a>. On Linux, the dirent structure is defined as follows:<\/p>\n<pre><code class=\"c\">struct dirent {\n    ino_t          d_ino;       \/* inode number *\/\n    off_t          d_off;       \/* offset to the next dirent *\/\n    unsigned short d_reclen;    \/* length of this record *\/\n    unsigned char  d_type;      \/* type of file; not supported\n                                   by all file system types *\/\n    char           d_name[256]; \/* filename *\/\n};\n<\/code><\/pre>\n<h3>file type<\/h3>\n<p>We can use variable members <code>d_type<\/code> in <code>dirent<\/code> to see if the current file is a regular file or a diretory.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary In this post, I will introduce how to get a vector of files in a directory in C++. Instead of filesystem in boost or C++ 17, this method is purely based on C++ 11 and Unix platforms. Details The following codes are self-explained. \/\/ safe path join in unix-based system string path_join(const string&amp; p1,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,5],"tags":[],"class_list":["post-184","post","type-post","status-publish","format-standard","hentry","category-c","category-proglang"],"_links":{"self":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/comments?post=184"}],"version-history":[{"count":1,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/184\/revisions"}],"predecessor-version":[{"id":185,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/184\/revisions\/185"}],"wp:attachment":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/media?parent=184"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/categories?post=184"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/tags?post=184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}