MRPT  2.0.4
CDirectoryExplorer.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "system-precomp.h" // Precompiled headers
11 
12 #ifdef _WIN32
13 #ifdef _MSC_VER
14 #include <sys/utime.h>
15 #endif
16 #include <windows.h>
17 
18 #include <direct.h>
19 #include <io.h>
20 #else
21 #include <dirent.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <utime.h>
25 #include <cerrno>
26 #include <cstring>
27 #include <ctime>
28 #endif
29 
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <algorithm>
33 #include <cstdio>
34 #include <iostream>
35 #include <queue>
36 
37 #include <mrpt/core/exceptions.h>
39 #include <mrpt/system/filesystem.h>
40 
41 using namespace mrpt::system;
42 using namespace std;
43 
44 /*---------------------------------------------------------------
45  explore
46  ---------------------------------------------------------------*/
48  const string& path, const unsigned long in_mask, TFileInfoList& outList)
49 {
51 
52  unsigned long mask = in_mask;
53 
54  outList.clear();
55 
56  // The path terminated in "/" or "\\"
57  string searchPath(path);
58  if (searchPath.size())
59  if (searchPath[searchPath.size() - 1] != '\\' &&
60  searchPath[searchPath.size() - 1] != '/')
61  {
62 #ifdef _WIN32
63  searchPath += '\\';
64 #else
65  searchPath.push_back('/');
66 #endif
67  }
68 
69  // cout << "searchPath:"<<searchPath<<endl;
70 
71 #ifdef _WIN32
72  // ====================
73  // WINDOWS VERSION
74  // ====================
75  WIN32_FIND_DATAA f;
76  TFileInfo newEntry;
77 
78  string searchPath_mask = searchPath + string("*.*");
79 
80  HANDLE h = FindFirstFileA(searchPath_mask.c_str(), &f);
81  if (h == INVALID_HANDLE_VALUE)
82  THROW_EXCEPTION("Error starting exploration! (does path exist?)");
83 
84  // Include the FILE_ATTRIB_ARCHIVE flag for files:
85  if (mask & FILE_ATTRIB_ARCHIVE) mask |= FILE_ATTRIBUTE_NORMAL;
86  do
87  {
88  if ((mask & f.dwFileAttributes) != 0) // Passes the user masks:
89  {
90  // File name:
91  newEntry.name = string(f.cFileName);
92 
93  // Complete file path:
94  newEntry.wholePath = searchPath;
95  newEntry.wholePath += newEntry.name;
96 
97  // File size:
98  newEntry.fileSize = ((uint64_t)f.nFileSizeLow) +
99  (((uint64_t)f.nFileSizeHigh) << 32);
100 
101  // File times:
102  struct stat statDat;
103  if (stat(newEntry.wholePath.c_str(), &statDat))
104  {
105  FindClose(h);
107  "Cannot get stat for file: '%s'",
108  newEntry.wholePath.c_str());
109  }
110 
111  newEntry.modTime = statDat.st_mtime;
112  newEntry.accessTime = statDat.st_atime;
113 
114  // Flags:
115  newEntry.isDir = 0 != (statDat.st_mode & _S_IFDIR);
116  newEntry.isSymLink =
117  false; // (We donnot look for this in Windows, by now...)
118 
119  // Save:
120  outList.push_back(newEntry);
121  }
122  } while (FindNextFileA(h, &f));
123 
124  FindClose(h); // Ignore possible errors..
125 
126 // Done
127 #else
128  // ====================
129  // LINUX VERSION
130  // ====================
131  TFileInfo newEntry;
132  struct dirent* ent;
133 
134  DIR* dir = opendir(searchPath.c_str());
135  if (!dir) THROW_EXCEPTION("Error starting exploration! (does path exist?)");
136 
137  while ((ent = readdir(dir)) != nullptr)
138  {
139  if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0)
140  {
141  // File name:
142  newEntry.name = string(ent->d_name);
143 
144  // Complete file path:
145  newEntry.wholePath = searchPath;
146  newEntry.wholePath += newEntry.name;
147 
148  // File times:
149  struct stat statDat
150  {
151  }, lstatDat{};
152  if (stat(newEntry.wholePath.c_str(), &statDat))
153  {
154  closedir(dir);
156  "Cannot get stat for file: '%s'",
157  newEntry.wholePath.c_str());
158  }
159 
160  newEntry.modTime = statDat.st_mtime;
161  newEntry.accessTime = statDat.st_atime;
162 
163  // Flags:
164  newEntry.isDir = S_ISDIR(statDat.st_mode);
165 
166  if (((mask & FILE_ATTRIB_ARCHIVE) != 0 && !newEntry.isDir) ||
167  ((mask & FILE_ATTRIB_DIRECTORY) != 0 && newEntry.isDir))
168  {
169  // File size:
170  newEntry.fileSize = (intmax_t)statDat.st_size;
171 
172  // Is it a symbolic link?? Need to call "lstat":
173  if (!lstat(newEntry.wholePath.c_str(), &lstatDat))
174  {
175  newEntry.isSymLink = S_ISLNK(lstatDat.st_mode);
176  }
177  else
178  newEntry.isSymLink = false;
179 
180  // Save:
181  outList.push_back(newEntry);
182  }
183  }
184  }
185 
186  closedir(dir);
187 
188 // Done
189 #endif
190 
191  MRPT_END
192 }
193 
194 // Auxiliary function to order by name, ascending
198 {
199  return a.wholePath < b.wholePath;
200 }
204 {
205  return a.wholePath > b.wholePath;
206 }
207 
208 /*---------------------------------------------------------------
209  sortByName
210  ---------------------------------------------------------------*/
212  TFileInfoList& lstFiles, bool ascendingOrder)
213 {
214  std::sort(
215  lstFiles.begin(), lstFiles.end(),
217 }
218 
219 /*---------------------------------------------------------------
220  filterByExtension
221  ---------------------------------------------------------------*/
223  TFileInfoList& lstFiles, const std::string& extension)
224 {
225  int i, n = (int)lstFiles.size();
226  for (i = n - 1; i >= 0; i--)
227  {
228  if (0 !=
229  os::_strcmpi(
230  mrpt::system::extractFileExtension(lstFiles[i].name).c_str(),
231  extension.c_str()))
232  {
233  // Does not match:
234  lstFiles.erase(lstFiles.begin() + i);
235  }
236  }
237 }
static void filterByExtension(TFileInfoList &lstFiles, const std::string &extension)
Remove from the list of files those whose extension does not coincide (without case) with the given o...
static void explore(const std::string &path, const unsigned long mask, TFileInfoList &outList)
The path of the directory to examine must be passed to this constructor, among the According to the f...
#define MRPT_START
Definition: exceptions.h:241
std::string wholePath
The whole file path.
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
std::deque< TFileInfo > TFileInfoList
The list type used in "explore".
bool cmpFileEntriesName_Desc(const CDirectoryExplorer::TFileInfo &a, const CDirectoryExplorer::TFileInfo &b)
STL namespace.
This represents the information about each file.
#define FILE_ATTRIB_ARCHIVE
time_t accessTime
Access and modification times.
uint64_t fileSize
The size of the file in bytes.
std::string extractFileExtension(const std::string &filePath, bool ignore_gz=false)
Extract the extension of a filename.
Definition: filesystem.cpp:98
static void sortByName(TFileInfoList &lstFiles, bool ascendingOrder=true)
Sort the file entries by name, in ascending or descending order.
std::string name
The file name (without the whole path).
#define FILE_ATTRIB_DIRECTORY
#define MRPT_END
Definition: exceptions.h:245
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:69
int _strcmpi(const char *str1, const char *str2) noexcept
An OS-independent version of strcmpi.
Definition: os.cpp:331
bool cmpFileEntriesName_Asc(const CDirectoryExplorer::TFileInfo &a, const CDirectoryExplorer::TFileInfo &b)



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020