" <v> is a date (e.g. 2015.02.17) or number followed by an unit",
" units: m(inutes) h(hours), d(days). Default: m(inutes)",
" examples: -o25 --older-than=30d -o24h -o2009.3.2/12:00 -o1999.01.01",
+ "-q or --quiet",
+ " no additional information like runtime",
"-P<p> or --pathname-pattern=<p>",
" a list of patterns for the path (without basename) separated by ';'",
" Each pattern can contain '*' as wildcard",
" If the first character is '^' the pattern is a 'not pattern':"
- " A directory will be entered if at least one of the positive patterns and none",
- " of the 'not patterns' matches",
+ " A directory will be entered if at least one of the positive patterns",
+ " and none of the 'not patterns' matches",
" examples: '*;^*/.git/' '*/cache/;*/temp/",
"-p<p> or --basename-pattern=<p>",
" a list of patterns for the basename (filename without path) separated by ';'",
" A file will be found if at least one of the positive patterns and none",
" of the 'not patterns' matches",
" examples: '*.cpp;*.hpp;Make*' '*;^*.bak;^*~",
+ "-t<n> or --trace-interval=<n> Default: 0",
+ " all <n> seconds the current path will be traced",
+ " 0: no trace",
"-t<l> or --type=<l>",
" the file type",
" <l> is a list of <v> values:",
- " <v>: d(irectory) f(file) r(egular file) l(ink)",
- " examples: -td --type=dr",
+ " <v>: b(lock) c(har) d(irectory) (l)i(nkdir) l(ink) o(ther)",
+ " p(ipe) s(ocket) r(egular)",
+ " <v>-sets: S(pecial)=bcspo N(ondir)=Slr",
+ " examples: -td --type=dr -tNi",
"-y<v> or --younger-than=<v>",
" the modification date is younger than <v>",
" <v> is a date (e.g. 2015.02.17) or number followed by an unit",
m_programArgs.addInt("maxdepth", "maximal subdir depth", 'D', "max-depth", 512);
m_programArgs.addInt("mindepth", "minimal subdir depth", 'd', "min-depth", 512);
m_programArgs.addString("older", "older than", 'o', "older-than", false, NULL);
- m_programArgs.addString("type", "file type", 't', "type", false, "df");
+ m_programArgs.addString("nodepattern", "pattern list for the basename", 'p', "basename-pattern", false, NULL);
+ m_programArgs.addString("pathpattern", "pattern list for the path", 'P', "path-pattern", false, NULL);
+ m_programArgs.addBool("quiet", "suppress additional info", 'q', "quiet", false);
+ m_programArgs.addInt("trace", "trace interval", 'T', "trace-interval", 0);
+ m_programArgs.addString("type", "file type", 't', "type", false, NULL);
m_programArgs.addString("younger", "younger than", 'y', "younger-than", false, NULL);
m_programArgs.addString("maxsize", "maximal filesize", 'Z', "max-size", false, NULL);
m_programArgs.addString("minsize", "minimal filesize", 'z', "min-size", false, NULL);
- m_programArgs.addString("nodepattern", "pattern list for the basename", 'p', "basename-pattern", false, NULL);
- m_programArgs.addString("pathpattern", "pattern list for the path", 'P', "path-pattern", false, NULL);
}
/**
break;
default:
throw ReOptionException(&m_programArgs,
- i18n("invalid <unit> expected. b k K m M g G"),
+ i18n("invalid <unit>. Expected: b k K m M g G"),
value);
}
break;
default:
throw ReOptionException(&m_programArgs,
- i18n("invalid size value: <number><unit> expected. <unit>: b k K m M g G"),
+ i18n("invalid size value: <number><unit> <unit>: b k K m M g G"),
value);
}
return rc;
}
+/**
+ * Checks whether the given value is a valid filetype list.
+ *
+ * @param value value to check
+ * @return the bitmask
+ * @throws ReOptionExecption
+ */
+ReDirStatus_t::Type_t ReDirOptions::checkType(const char* value){
+ int rc = ReDirStatus_t::TF_UNDEF;
+ while (*value != '\0'){
+ switch(*value){
+ case 'b':
+ rc |= ReDirStatus_t::TF_BLOCK;
+ break;
+ case 'c':
+ rc |= ReDirStatus_t::TF_CHAR;
+ break;
+ case 'd':
+ rc |= ReDirStatus_t::TF_SUBDIR;
+ break;
+ case 'i':
+ rc |= ReDirStatus_t::TF_LINK_DIR;
+ break;
+ case 'l':
+ rc |= ReDirStatus_t::TF_LINK;
+ break;
+ case 'o':
+ rc |= ReDirStatus_t::TF_OTHER;
+ break;
+ case 'p':
+ rc |= ReDirStatus_t::TF_PIPE;
+ break;
+ case 's':
+ rc |= ReDirStatus_t::TF_SOCKET;
+ break;
+ case 'r':
+ rc |= ReDirStatus_t::TF_REGULAR;
+ break;
+ case 'S':
+ rc |= ReDirStatus_t::TC_SPECIAL;
+ break;
+ case 'N':
+ rc |= ReDirStatus_t::TC_NON_DIR;
+ break;
+ case ' ':
+ case ',':
+ break;
+ default:
+ throw ReOptionException(&m_programArgs,
+ i18n("invalid type: $1 Expected: b(lock) c(har) d(irectory)"
+ " (l)i(nkdir) l(ink) o(ther) p(ipe) s(ocket) r(egular)"
+ " S(pecial=bcspo) N(ondir=Slr)"),
+ value);
+ }
+ value++;
+ }
+ return (ReDirStatus_t::Type_t) rc;
+}
/**
* Sets the standard filter options given by the program arguments.
filter.m_maxSize = checkSize(buffer.str());
if (m_programArgs.getString("minsize", buffer)[0] != '\0')
filter.m_minSize = checkSize(buffer.str());
+ if (m_programArgs.getString("type", buffer)[0] != '\0')
+ filter.m_types = checkType(buffer.str());
filter.m_minDepth = m_programArgs.getInt("mindepth");
filter.m_maxDepth = m_programArgs.getInt("maxdepth");
if (m_programArgs.getString("nodepattern", buffer) != NULL){
m_pathPatterns.set(buffer.str());
filter.m_pathPatterns = &m_nodePatterns;
}
+ filter.m_traceInterval = m_programArgs.getInt("trace");
}
/**
* Prints a help message, the error message and exits.
ReByteBuffer buffer;
checkDate(m_programArgs.getString("older", buffer));
checkDate(m_programArgs.getString("younger", buffer));
- const char* value = m_programArgs.getString("type", buffer);
- if (strspn (value, "dfrl") != strlen(value))
- throw ReOptionException(&m_programArgs,
- i18n("unknown file type. Expected: d(irectory) f(file) r(egular file) l(ink)"),
- value);
+ checkType(m_programArgs.getString("types", buffer));
checkSize(m_programArgs.getString("maxsize", buffer));
checkSize(m_programArgs.getString("minsize", buffer));
}
void ReDirList::list(int argc, char* argv[]){
ReDirEntryFilter_t filter;
try {
+ time_t start = time(NULL);
m_programArgs.init(argc, argv);
+ bool verbose = ! m_programArgs.getBool("quiet");
setFilterFromProgramArgs(filter);
if (m_programArgs.getArgCount() == 0)
help(i18n("no arguments given (missing path)"));
ReByteBuffer bufferRights;
ReByteBuffer bufferTime;
+ int64_t sumSizes = 0;
+ int files = 0;
+ int dirs = 0;
for (int ix = 0; ix < m_programArgs.getArgCount(); ix++){
ReTraverser traverser(m_programArgs.getArg(ix));
traverser.setMinLevel(filter.m_maxDepth);
int level;
ReDirStatus_t* entry;
while( (entry = traverser.nextFile(level, &filter)) != NULL){
+ if (entry->isDirectory())
+ dirs++;
+ else{
+ files++;
+ sumSizes += entry->fileSize();
+ }
if (! printOneFile(entry))
- printf("%s %12lld %s %s%s\n",
- entry->rightsAsString(bufferRights), entry->fileSize(),
+ printf("%s %12.6f %s %02x %s%s\n",
+ entry->rightsAsString(bufferRights), entry->fileSize() / 1E6,
entry->filetimeAsString(bufferTime),
+ entry->type(),
entry->m_path.str(), entry->node());
}
}
+ if (verbose){
+ int duration = int(time(NULL) - start);
+ printf ("+++ %d dirs and %d file(s) with %.6f MByte in %02d:%02d sec\n",
+ dirs, files, sumSizes / 1E6, duration / 60, duration % 60);
+ }
} catch(ReOptionException& exc){
help(exc.getMessage());
}
*/\r
const char* ReDirStatus_t::filetimeAsString(ReByteBuffer& buffer) {\r
time_t time1 = filetimeToTime(modified());\r
- struct tm* time2 = localtime(&time1);\r
- buffer.setLength(4+2*1+2*2+1+3*2+2*1);\r
- strftime(buffer.buffer(), buffer.length(), "%y.%m.%d %H:%M:%S", time2);\r
+ struct tm* time2 = gmtime(&time1);\r
+ buffer.setLength(4+2*2+2*2+1+3*2+2*1);\r
+ strftime(buffer.buffer(), buffer.length(), "%Y.%m.%d %H:%M:%S", time2);\r
return buffer.str();\r
}\r
+\r
+\r
/**\r
* Tests whether the instance contains data about "." or "..".\r
*\r
#endif\r
return rc;\r
}\r
+\r
+/**\r
+ * Returns the type of the entry.\r
+ * return the file type, e.g. TF_REGULAR\r
+ */\r
+ReDirStatus_t::Type_t ReDirStatus_t::type(){
+ Type_t rc = TF_UNDEF;
+#if defined __linux__\r
+#elif defined __WIN32__\r
+ int flags = (m_data.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY\r
+ | FILE_ATTRIBUTE_HIDDEN \r
+ | FILE_ATTRIBUTE_SYSTEM \r
+ | FILE_ATTRIBUTE_ARCHIVE \r
+ | FILE_ATTRIBUTE_NORMAL\r
+ | FILE_ATTRIBUTE_TEMPORARY \r
+ | FILE_ATTRIBUTE_SPARSE_FILE \r
+ | FILE_ATTRIBUTE_COMPRESSED \r
+ | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED \r
+ | FILE_ATTRIBUTE_ENCRYPTED \r
+ | FILE_ATTRIBUTE_HIDDEN));\r
+\r
+ if (0 == flags)\r
+ rc = TF_REGULAR;\r
+ else if (0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){\r
+ rc = (0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))\r
+ ? TF_LINK_DIR : TF_SUBDIR;\r
+ } else if (0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))\r
+ rc = TF_LINK;\r
+ else\r
+ rc = TF_OTHER;\r
+#endif\r
+ return rc;
+}
+\r
/**\r
* Tests whether the instance is a directory.\r
*\r
#ifdef __linux__\r
return (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_REG) || S_ISREG(getStatus()->st_mode);\r
#elif defined __WIN32__\r
- return 0 != (m_data.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));\r
+ return 0 == (m_data.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));\r
#endif\r
}\r
/**\r
* Constructor.\r
*/\r
ReDirEntryFilter_t::ReDirEntryFilter_t() :\r
- m_regulars(true),\r
- m_specials(true),\r
- m_directories(true),\r
+ m_types(ReDirStatus_t::TC_ALL),\r
m_nodePatterns(),\r
m_pathPatterns(),\r
m_minSize(0),\r
m_minAge(0),\r
m_maxAge(0),\r
m_minDepth(0),\r
- m_maxDepth(512)\r
+ m_maxDepth(512),\r
+ m_traceInterval(0),
+ m_lastTrace(0),\r
+ m_traceCounter(0)\r
{\r
}\r
\r
bool ReDirEntryFilter_t::match(ReDirStatus_t& entry){\r
bool rc = false;\r
do {\r
- if (! m_directories && entry.isDirectory())\r
- break;\r
- if (m_specials && (entry.isDirectory() || entry.isRegular()))\r
- break;\r
- if (m_regulars && ! entry.isRegular())\r
+ if (m_traceCounter++ % 100 == 0 && m_traceInterval > 0){\r
+ time_t now = time(NULL);\r
+ if (int(now - m_lastTrace) > m_traceInterval){\r
+ m_lastTrace = now;\r
+ fprintf(stderr, "%s%s\n", entry.m_path.str(), entry.node());\r
+ }\r
+ }\r
+ if (0 == (entry.type() & m_types))\r
break;\r
if (m_minSize > 0 && entry.fileSize() > m_minSize)\r
break;\r