LC_SET_PROPERTIES_2, // 50110
LC_SET_PROPERTIES_3, // 50111
};
-const char* ReDirTools::m_version = "2015.01.30";
+const char* ReDirTools::m_version = "2015.02.04";
static const char* s_helpSummary[] = {
"dirtool or dt <command> <opts>",
m_output(stdout),
m_verboseLevel(V_NORMAL)
{
+ m_nodePatterns.setIgnoreCase(true);
+ m_pathPatterns.setIgnoreCase(true);
}
/**
* Destructor.
"A directory will be entered if at least one of the positive patterns\n"
"and none of the 'not patterns' matches\n"
"examples:\n"
- "';*/music/;pic*' enters music and xy/Music and PIC and pictures but not xy/pic and img\n"
- "';*;-*/.git;.hg' ignores .git and xy/z/.git and .ht, but enters xy/.hg"),
+ "';music;pic*' enters music and xy/Music and PIC and pictures but not xy/pic and img\n"
+ "';*;-.git;.hg' ignores .git and xy/z/.git and .ht"),
'P', "path-pattern", false, NULL);
m_programArgs.addString("nodepattern",
i18n("a list of patterns for the basename (name without path) separated by ';'\n"
throw ReOptionException(&m_programArgs,
i18n("invalid separator (first character): $1 use ';' instead"),
value);
+ if (strchr(value, OS_SEPARATOR_CHAR) != NULL)
+ throw ReOptionException(&m_programArgs,
+ i18n("slash not allowed in pattern list: $2"), value);
return value;
}
/**
}
}
}
+
+/**
+ * Constructor.
+ *
+ * @param usage a string vector with a message how to use the command
+ * @param example a string vector with some examples how to use the command
+ */
+ReTool::ReTool(const char* usage[], const char* example[]) :
+ ReDirOptions(usage, example),
+ ReDirStatisticData(),
+ m_traverser(NULL)
+{
+}
+
+/**
+ * Destructor.
+ */
+ReTool::~ReTool(){
+}
+
+/**\r
+ * Prints a message.\r
+ *\r
+ * Often overwritten by a subclass.\r
+ *\r
+ * @param currentFile message for the trace\r
+ * @return <code>true</code> (for chaining)\r
+ */\r
+bool ReTool::trace(const char* currentFile){
+ ReByteBuffer buffer(" ");
+ int duration = int(time(NULL) - m_startTime);
+ buffer.appendInt(duration / 60).appendInt(duration % 60, ":%02d: ");
+ buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser->directories()).append(" dir(s)");
+ buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser->files()).append(" dir(s)");
+ buffer.append(currentFile);
+ fputs(buffer.str(), stdout);
+ return true;
+}
/**
* Constructor.
*/
m_traceInterval(0),
m_lastTrace(0)
{
+ // standard short options: D d O o P p T t v y Z z
m_programArgs.addBool("kbyte",
- i18n("output is '<kbyte> <path>' (like unix 'du' command)"),
+ i18n("output format is '<kbyte> <path>' (like unix 'du' command)"),
'k', "kbyte", false);
addStandardFilterOptions();
}
const ReStringList& ReDirStatistic::calculate(const char* base, int level,
void (*formatter)(const ReDirStatisticData& data, ReDirStatistic& parent,
ReByteBuffer& line)){
- ReDirEntryFilter_t filter;
+ ReDirEntryFilter_t filter;
ReTraverser traverser(base);
- setFilterFromProgramArgs(filter);
- traverser.setPropertiesFromFilter(&filter);
+ setFilterFromProgramArgs(filter);
+ traverser.setPropertiesFromFilter(&filter);
if (level > 1024)
level = 1024;
else if (level < 0)
ReDirStatisticData* current = dataStack[0];
current->m_path.set(base, -1);
ReByteBuffer line;
- int traceCount = 0;
bool useFilter = filter.m_minSize > 0 || filter.m_maxSize != -1
|| filter.m_minAge != 0 || filter.m_maxAge != 0
|| m_nodePatterns.count() > 0;
} else if (! useFilter || filter.match(*entry)){
current->m_sizes += entry->fileSize();
current->m_files++;
- if (++traceCount % 100 == 0 && m_traceInterval > 0){
- time_t now = time(NULL);
- int diff = int(now - m_lastTrace);
- if (diff >= m_traceInterval){
- fprintf(m_output, "%s\n", current->m_path.str());
- m_lastTrace = now;
- }
- }
}
}
// close all dirs with parents:
* Constructor.
*/
ReDirList::ReDirList() :
- ReDirOptions(s_listUsage, s_listExamples)
+ ReTool(s_listUsage, s_listExamples)
{
m_programArgs.addBool("short", i18n("output is only path and basename"),
'1', "--short", false);
* Constructor.
*/
ReDirBatch::ReDirBatch() :
- ReDirOptions(s_batchUsage, s_batchExamples)
+ ReTool(s_batchUsage, s_batchExamples)
{
// standard short options: D d O o P p T t v y Z z
m_programArgs.addString("first",
* Constructor.
*/
ReDirSync::ReDirSync() :
- ReDirOptions(s_syncUsage, s_syncExamples),
+ ReTool(s_syncUsage, s_syncExamples),
m_buffer()
{
// standard short options: D d O o P p T t v y Z z
#ifndef OS_DIRTOOLS_HPP_
#define OS_DIRTOOLS_HPP_
-class ReDirOptions : ReTraceUnit{
+class ReDirOptions : public ReTraceUnit{
public:
enum VerboseLevel {
V_UNDEF,
} ReFileProperties_t;
#endif
-class ReDirBatch : public ReDirOptions {
+class ReDirStatisticData{
+public:
+ ReDirStatisticData();
+ ReDirStatisticData(const ReDirStatisticData& source);
+ ReDirStatisticData& operator =(const ReDirStatisticData& source);
+public:
+ void clear();
+ ReDirStatisticData& add(const ReDirStatisticData& source);
+public:
+ int64_t m_sizes;
+ int m_files;
+ int m_dirs;
+ ReByteBuffer m_path;
+};
+
+class ReTool : public ReDirOptions, public ReDirStatisticData {
+public:
+ ReTool(const char* usage[], const char* example[]);
+ virtual ~ReTool();
+public:
+ virtual bool trace(const char* currentFile);
+protected:
+ ReTraverser* m_traverser;
+};
+
+class ReDirBatch : public ReTool {
public:
ReDirBatch();
public:
{ return false; }
};
-class ReDirSync : public ReDirOptions {
+class ReDirSync : public ReTool {
public:
ReDirSync();
public:
ReByteBuffer m_buffer;
};
-class ReDirList : public ReDirOptions {
+class ReDirList : public ReTool {
public:
ReDirList();
public:
};
-class ReDirStatisticData{
-public:
- ReDirStatisticData();
- ReDirStatisticData(const ReDirStatisticData& source);
- ReDirStatisticData& operator =(const ReDirStatisticData& source);
-public:
- void clear();
- ReDirStatisticData& add(const ReDirStatisticData& source);
-public:
- int64_t m_sizes;
- int m_files;
- int m_dirs;
- ReByteBuffer m_path;
-};
class ReDirStatistic;
extern void formatLikeDu(const ReDirStatisticData& data, ReDirStatistic& parent,
return &m_status;\r
}\r
#endif\r
-
-/**
-* Constructor.
-*
-* @param triggerCount efficiency: only every N calls a time check takes place
-* @param interval the minimum number of seconds between two traces
-*/
-ReTraceUnit::ReTraceUnit(int triggerCount, int interval) :
- m_count(0),
- m_triggerCount(triggerCount),
- m_lastTrace(time(NULL)),
- m_interval(interval)
-{
-}
-/**
- * Destructor.
- */
-ReTraceUnit::~ReTraceUnit(){
-}
+\r
+/**\r
+* Constructor.\r
+*\r
+* @param triggerCount efficiency: only every N calls a time check takes place\r
+* @param interval the minimum number of seconds between two traces\r
+*/\r
+ReTraceUnit::ReTraceUnit(int triggerCount, int interval) :\r
+ m_count(0),\r
+ m_triggerCount(triggerCount),\r
+ m_lastTrace(0),\r
+ m_interval(interval),\r
+ m_startTime(time(NULL))\r
+{\r
+ m_lastTrace = m_startTime;\r
+}\r
+/**\r
+ * Destructor.\r
+ */\r
+ReTraceUnit::~ReTraceUnit(){\r
+}\r
\r
/**\r
* Prints a message.\r
* @param message message for the trace\r
* @return <code>true</code> (for chaining)\r
*/\r
-bool ReTraceUnit::trace(const char* message){
- printf("%d\n", message);
- return true;
-}
+bool ReTraceUnit::trace(const char* message){\r
+ printf("%d\n", message);\r
+ return true;\r
+}\r
\r
/**\r
* Constructor.\r
again = true;\r
if (m_level < m_maxLevel && current->isDirectory()\r
&& ! current->isDotDir() && ! current->isLink()\r
- && (m_dirPatterns == NULL || isAllowedDir(current->m_path,\r
- current->node()))){\r
+ && (m_dirPatterns == NULL \r
+ || isAllowedDir(current->node()))){\r
// open a new level\r
alreadyRead = initEntry(current->m_path, current->node() , m_level + 1);\r
m_directories++;\r
int m_triggerCount;
time_t m_lastTrace;
int m_interval;
+ time_t m_startTime;
};
#define MAX_ENTRY_STACK_DEPTH 256
class ReTraverser {
void freeEntry(int level);
/**
* Tests whether a directory should be processed.
- * @param path the path of the subdir
* @param node the base name of the subdir
* @return <code>true</code>: the subdir will be processed<br>
* <code>false</code>: do not enter this subdir
*/
- inline bool isAllowedDir(ReByteBuffer& path, const char* node){
- int ix = path.length();
- bool rc = m_dirPatterns->match(path.append(node));
- path.setLength(ix);
+ inline bool isAllowedDir(const char* node){
+ bool rc = m_dirPatterns->match(node);
return rc;
}
protected:
virtual bool match(const ReByteBuffer& toTest, ReHit* hit = NULL) const;
virtual bool search(const ReByteBuffer& toTest, ReHit* hit = NULL,
bool greedy = false) const;
+ /** Sets the mode whether the case will be ignored or not.
+ * @param onNotOff <code>true</code>: the case will be ignored.
+ */
+ void setIgnoreCase(bool onNotOff){
+ m_ignoreCase = onNotOff;
+ }
const char* status(ReByteBuffer& buffer, const char* prefix) const;
protected:
bool searchTokens(const ReByteBuffer& toTest, int from, int to,
private:
ReByteBuffer m_pattern;
ReStringList m_tokens;
+ bool m_ignoreCase;
};
-class RePatternList{
+class RePatternList {
public:
RePatternList();
~RePatternList();
/** Returns the original pattern string.
* @return the string describing the patterns.
*/
- const char* patternString() const
- { return m_patternString.str(); }
+ const char* patternString() const
+ { return m_patternString.str(); }
void set(const char* patterns, bool ignoreCase = false,
const char* separator = NULL, const char* notPrefix = "-");
const char* status(ReByteBuffer& buffer, const char* prefix) const;
+ /** Sets the mode whether the case will be ignored or not.
+ * @param onNotOff <code>true</code>: the case will be ignored.
+ */
+ void setIgnoreCase(bool onNotOff){
+ for (int ii = 0; ii < m_count; ii++)
+ m_patterns[ii]->setIgnoreCase(onNotOff);
+ }
private:
int setOne(int index, const char* pattern, size_t patternLength,
bool ignoreCase, const ReByteBuffer& notPrefix);