Linux下遍歷指定目錄的C 實現

Linux下遍歷指定目錄的C  實現

        之前在 https://blog.csdn.net/fengbingchun/article/details/51474728 給出了在Windows遍歷指定資料夾的C 實現,這裡給出在Linux下遍歷目錄的實現,Windows和Linux下的實現都是參考了OpenCV 2.x中的實現,OpenCV中的用法可參考https://blog.csdn.net/fengbingchun/article/details/42435901 ,OpenCV 3.x中將這一部分移除掉了。

        目前不論是windows、linux還是opencv本身的實現,在目錄中巢狀的目錄只能遍歷一層。

        測試程式碼如下:

#include <dirent.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <string>
namespace {
void Usage(const char* exe)
{
fprintf(stderr, "input params error, run this exe as following command line:\n");
fprintf(stderr, "\t%s arg1 arg2 arg3\n", exe);
fprintf(stderr, "\targ1: specify the directory to traverse\n");
fprintf(stderr, "\targ2: type:\n"
"\t\t0: tarverse all files and all directories in directory;\n"
"\t\t1: only tarverse all files, don't include directories in directory;\n"
"\t\t2: only tarverse all directories, don't include files in directory.\n");
fprintf(stderr, "\targ3: optional, filter, default is *, which is don't filter. \n");
fprintf(stderr, "for example(support relative path), only traverse jpg image:\n");
fprintf(stderr, "\t%s ./images 0 .jpg\n", exe);
fprintf(stderr, "##### test fail #####\n");
}
// 遍歷指定資料夾下的所有檔案,不包括指定資料夾內的資料夾
std::vector<std::string> GetListFiles(const std::string& path, const std::string& exten = "*")
{
std::vector<std::string> list;
list.clear();
DIR* dp = nullptr;
struct dirent* dirp = nullptr;
if ((dp = opendir(path.c_str())) == nullptr) {
return list;
}
while ((dirp = readdir(dp)) != nullptr) {
if (dirp->d_type == DT_REG) {
if (exten.compare("*") == 0)
list.emplace_back(static_cast<std::string>(dirp->d_name));
else
if (std::string(dirp->d_name).find(exten) != std::string::npos)
list.emplace_back(static_cast<std::string>(dirp->d_name));
}
}
closedir(dp);
return list;
}
// 遍歷指定資料夾下的所有資料夾,不包括指定資料夾下的檔案
std::vector<std::string> GetListFolders(const std::string& path, const std::string& exten = "*")
{
std::vector<std::string> list;
list.clear();
DIR* dp = nullptr;
struct dirent* dirp = nullptr;
if ((dp = opendir(path.c_str())) == nullptr) {
return list;
}
while ((dirp = readdir(dp)) != nullptr) {
if (dirp->d_type == DT_DIR && strcmp(dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0) {
if (exten.compare("*") == 0)
list.emplace_back(static_cast<std::string>(dirp->d_name));
else
if (std::string(dirp->d_name).find(exten) != std::string::npos)
list.emplace_back(static_cast<std::string>(dirp->d_name));
}
}
closedir(dp);
return list;
}
// 遍歷指定資料夾下的所有檔案,包括指定資料夾內的資料夾
std::vector<std::string> GetListFilesR(const std::string& path, const std::string& exten = "*")
{
std::vector<std::string> list = GetListFiles(path, exten);
std::vector<std::string> dirs = GetListFolders(path, exten);
for (auto it = dirs.cbegin(); it != dirs.cend();   it) {
std::vector<std::string> cl = GetListFiles(*it, exten);
for (auto file : cl) {
list.emplace_back(*it   "/"   file);
}
}
return list;
}
} // namespace
int main(int argc, char* argv[])
{
if (argc < 3 || argc > 4) {
Usage(argv[0]);
return -1;
}
int type = atoi(argv[2]);
std::string exten = "*";
if (argc == 4) exten = std::string(argv[3]);
std::vector<std::string> vec;
if (type == 0) vec = GetListFilesR(std::string(argv[1]), exten);
else if (type == 1) vec = GetListFiles(std::string(argv[1]), exten);
else if (type == 2) vec = GetListFolders(std::string(argv[1]), exten);
else { Usage(argv[0]); return -1;}
fprintf(stdout, "traverse result: files count: %d\n", vec.size());
for (auto& file : vec) {
fprintf(stderr, "\t%s\n", file.c_str());
}
fprintf(stdout, "===== test success =====\n");
}

        CMakeLists.txt檔案內容如下:

PROJECT(samples_cplusplus)
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
# 支援C  11
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O2 -std=c11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -g -Wall -O2 -std=c  11")
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})
FILE(GLOB samples ${PROJECT_SOURCE_DIR}/*.cpp)
FOREACH (sample ${samples})
STRING(REGEX MATCH "[^/] $" sample_file ${sample})
STRING(REPLACE ".cpp" "" sample_basename ${sample_file})
ADD_EXECUTABLE(test_${sample_basename} ${sample})
TARGET_LINK_LIBRARIES(test_${sample_basename} pthread)
ENDFOREACH()

        build.sh指令碼內容如下:

#! /bin/bash
echo "Note: new create build directory, and executable file in build"
echo ${PWD}
mkdir -p build
cd build
cmake ..
make

        執行過程:將終端定位到Linux_Code_Test/Samples_cplusplus目錄下,執行:./build.sh,然後進入到build目錄下,執行生成的執行檔案即可。

        測試結果如下:

        GitHub: https://github.com/fengbingchun/Linux_Code_Test