"statistic shows statistics about a direcctory tree",\r
"synchronize copies only modified or new files from",\r
" from a source directory tre to a target",\r
+ "touch sets the filetimes",\r
NULL\r
};\r
\r
const char* s_batchUsage[] = {\r
- "<command>: batch",\r
+ "<command>: batch [<opts>] <dir_or_file1> [<dir_or_file2> ...]",\r
" produces output usable for a batch file (script)",\r
" all found files can be processed with a given script",\r
" each line starts (usually) with a script name (see -c)",\r
};\r
\r
const char* s_listUsage[] = {\r
- "<command>: list",\r
+ "<command>: l(ist) [<opts>] <dir_or_file1> [<dir_or_file2> ...]",\r
" lists the metadata (size, modification date ...) of the selected files",\r
NULL\r
};\r
const char* s_listExamples[] = {\r
"dirtool list --min-size=10M e:\\data",\r
- "dirtool list --type=f -y7d --size=10M -p;*.cpp;*.hpp;Makefile*;-*~ /home/data" ,\r
+ "dirtool li --type=f -y7d --size=10M -p;*.cpp;*.hpp;Makefile*;-*~ /home/data",\r
NULL\r
};\r
\r
static const char* s_statisticUsage[] = {\r
- "<command>:"\r
- "st(atistic) [<opts_stat>] <path> [<depth>]",\r
+ "<command>: st(atistic) [<opts>] <path1> [<path2> ...] [<depth>]",\r
" shows a statistic about a directory tree",\r
"<path> a directory path: relative or absolute",\r
"<depth> 0: only the summary of <path> will be shown",\r
};\r
const char* s_statisticExamples[] = {\r
"dirtool st -q -t0 e:\\windows", \r
- "dirtool statistic --quiet --kbyte --trace-interval=60 ../mail 2", \r
+ "dirtool statistic --quiet --kbyte --trace-interval=60 ../mail ../remember 2",\r
"dirtool stat -q --kbyte d:data 2", \r
NULL\r
};\r
\r
const char* s_syncUsage[] = {\r
- "<command>:",\r
- "sy(nchronize) <opts> <source1> [<source2> ...] <target>",\r
+ "<command>: sy(nchronize) <opts> <source1> [<source2> ...] <target>",\r
" Synchronizes the content of a directory tree with another.",\r
" Newer or missing files will be copied",\r
" If a source name ends with the separator (/ in linux, \\ in win) the target",\r
NULL\r
};\r
\r
+const char* s_touchUsage[] = {\r
+ "<command>: touch [<opts>] <dir_or_file1> [<dir_or_file2> ...]",\r
+ " sets the filetimes (modification and/or access time) of the selected files",\r
+ NULL\r
+};\r
+const char* s_touchExamples[] = {\r
+ "dirtool touch -p;*.csv -m2014.12.1/8:12 e:\\data e:\\history\\readme.txt",\r
+ "dirtool touch -p;*.cpp --modified=now-4d12H /home/data" ,\r
+ "dirtool touch -p;*.csv -m+1m . e:\\data e:\\history\\readme.txt",\r
+ NULL\r
+};\r
+\r
/**\r
* Constructor.\r
*\r
* Checks whether the given value is a time expression.\r
*\r
* Possible: <date> <date_time> <n><unit>\r
- * Units: m(inutes) h(our) d(ays)\r
+ * Units: m(inutes) h(our) d(ays) s(econds)\r
*\r
* @param value value to check\r
- * @return the value converted into the absolute time\r
+ * @return the value converted into the absolute (or relative) time\r
* @throws ReOptionExecption\r
*/\r
time_t ReDirOptions::checkDate(const char* value){\r
int year, month, day;\r
int hour = 0;\r
int minute = 0;\r
- switch (sscanf(value, "%d.%d.%d/%d:%dc", &year, &month, &day, &hour, &minute)){\r
+ int sec = 0;\r
+ switch (sscanf(value, "%d.%d.%d/%d:%d:%d", &year, &month, &day, &hour, &minute, &sec)){\r
case 3:\r
case 4:\r
- case 5:\r
+ case 5:\r
+ case 6:\r
{\r
if (year < 1970)\r
throw ReOptionException(&m_programArgs, \r
throw ReOptionException(&m_programArgs, \r
i18n("invalid date/date-time value. yyyy.mm.dd/hh:MM expected"), value);\r
}\r
+ } else if (theValue.count(":") >= 1){\r
+ // a time:\r
+ int hour = 0;\r
+ int minute = 0;\r
+ int sec = 0;\r
+ switch (sscanf(value, "%d:%d:%d", &hour, &minute, &sec)){\r
+ case 2:\r
+ case 3:\r
+ {\r
+ // the time (today)\r
+ rc = time(NULL) / 86400 * 86400 + hour * 3600 + minute * 60 + sec;\r
+ break;\r
+ }\r
+ default:\r
+ throw ReOptionException(&m_programArgs,\r
+ i18n("invalid time value. HH:MM:SS expected"), value);\r
+ }\r
} else {\r
// a time distance value:\r
char unit = 'm';\r
int count = 0;\r
- switch(sscanf(value, "%d%c", &count, &unit)){\r
+ int isNegative = false;\r
+ if (theValue.startsWith("now")){\r
+ rc = time(NULL);\r
+ theValue.remove(0, 3);\r
+ }\r
+ if (theValue.str()[0] == '-')\r
+ isNegative = true;\r
+ else if (theValue.startsWith("+"))\r
+ theValue.remove(0, 1);\r
+ switch(sscanf(theValue.str(), "%d%c", &count, &unit)){\r
case 1:\r
case 2:\r
switch(unit){\r
+ case 's':\r
+ break;\r
case 'm':\r
count *= 60;\r
break;\r
break;\r
default:\r
throw ReOptionException(&m_programArgs, \r
- i18n("invalid unit. expected: m(inutes) h(ours) d(ays)"), value);\r
+ i18n("invalid unit. expected: s(econds) m(inutes) h(ours) d(ays)"), value);\r
}\r
rc = time(NULL) - count;\r
break;\r
default:\r
throw ReOptionException(&m_programArgs, \r
- i18n("invalid relative time value <number><unit> expected. <unit>: m h d"), \r
+ i18n("invalid relative time value <number><unit> expected. <unit>: s m h d"),\r
value);\r
}\r
+ if (isNegative)\r
+ rc -= count;\r
+ else\r
+ rc += count;\r
}\r
return rc;\r
}\r
/**\r
* Constructor.\r
*\r
- * @param usage a string vector with a message how to use the command\r
- * @param example a string vector with some examples how to use the command\r
+ * @param usage a string vector with a message how to use the command\r
+ * @param example a string vector with some examples how to use the command\r
+ * @param minArguments minimal count of non option arguments\r
+ * @param reservedFirst count of arguments at the start which are not files\r
+ * @param reservedLast count of arguments at the end which are not files\r
+ * @param addCurrentDirIfNoArguments\r
+ * <code>true</code>: if no arguments are given the current\r
+ * directory will be added as argument\r
*/\r
-ReTool::ReTool(const char* usage[], const char* example[]) :\r
+ReTool::ReTool(const char* usage[], const char* example[],\r
+ int minArguments, int reservedFirst, int reservedLast,\r
+ bool addCurrentDirIfNoArguments) :\r
ReDirOptions(usage, example),\r
- ReDirStatisticData(),\r
- m_traverser(NULL)\r
+ ReDirTreeStatistic(),\r
+ m_minArguments(minArguments),\r
+ m_reservedFirst(reservedFirst),\r
+ m_reservedLast(reservedLast),\r
+ m_addCurrentDirIfNoArguments(addCurrentDirIfNoArguments),\r
+ m_traverser(NULL, this),\r
+ m_filter(),\r
+ m_start(time(NULL))\r
{\r
}\r
\r
ReByteBuffer buffer(" ");\r
int duration = int(time(NULL) - m_startTime);\r
buffer.appendInt(duration / 60).appendInt(duration % 60, ":%02d: ");\r
- buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser->directories()).append(" dir(s)");\r
- buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser->files()).append(" dir(s)");\r
+ buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser.directories()).append(" dir(s)");\r
+ buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser.files()).append(" dir(s)");\r
buffer.append(currentFile);\r
fputs(buffer.str(), stdout);\r
return true;\r
}\r
+\r
+/**\r
+ * Evaluates the arguments and calls the main function.\r
+ *\r
+ * @param argc number of arguments\r
+ * @param argv program arguments\r
+ * @param minArguments the command needs at least so many non option arguments\r
+ */\r
+void ReTool::run(int argc, const char** argv){\r
+ try {\r
+ m_programArgs.init(argc, argv);\r
+ if (m_programArgs.getArgCount() < m_minArguments)\r
+ m_programArgs.help(i18n("too few arguments"), false, stdout);\r
+ doIt();\r
+ } catch (ReOptionException& exc) {\r
+ m_programArgs.help(exc.getMessage(), false, stdout);\r
+ }\r
+}\r
+/**\r
+ * Evaluates the non option arguments which are names of files or directories.\r
+ *\r
+ * For each non reserved argument it will be called either <code>processSingleFile()</code>\r
+ * or <code>processTree()</code>.\r
+ *\r
+ */\r
+void ReTool::processFileArguments(){\r
+ int max = m_programArgs.getArgCount() - m_reservedLast;\r
+ struct stat info;\r
+ // Test whether the arguments are files or directories:\r
+ for (int ii = m_reservedFirst; ii < max; ii++){\r
+ const char* arg = m_programArgs.getArg(ii);\r
+ if (stat(arg, &info) != 0)\r
+ m_programArgs.help(\r
+ ReByteBuffer(i18n("not a file or a directory: ")).append(arg).str(),\r
+ false, stderr);\r
+ }\r
+ // process the files:\r
+ for (int ii = m_reservedFirst; ii < max; ii++){\r
+ const char* arg = m_programArgs.getArg(ii);\r
+ if (S_ISDIR(info.st_mode))\r
+ processTree(arg);\r
+ else\r
+ processSingleFile(arg);\r
+ }\r
+}\r
+/**\r
+ * Processes a single file.\r
+ *\r
+ * Gets the file info and calls <code>processFile()</code>.\r
+ *\r
+ * @param filename the name of the file\r
+ */\r
+void ReTool::processSingleFile(const char* filename){\r
+ ReByteBuffer protocol;\r
+ ReByteBuffer path;\r
+ ReByteBuffer name;\r
+ ReByteBuffer ext;\r
+ ReStringUtils::splitPath(filename, &protocol, &path, &name, &ext);\r
+ protocol.append(path);\r
+ if (protocol.length() == 0)\r
+ protocol.append(".");\r
+ else\r
+ protocol.setLength(protocol.length() - 1);\r
+ m_traverser.changeBase(protocol.str());\r
+\r
+ name.append(ext);\r
+ setFilterFromProgramArgs(m_filter);\r
+ m_traverser.setPropertiesFromFilter(&m_filter);\r
+ ReDirStatus_t entry;\r
+ entry.m_path = protocol;\r
+ if (entry.findFirst()){\r
+ do {\r
+#if defined __linux__\r
+ bool found = strcmp(entry.node(), name.str()) == 0;\r
+#elif defined __WIN32__\r
+ bool found = stricmp(entry.node(), name.str()) == 0;\r
+#endif\r
+ if (found && m_filter.match(entry)){\r
+ processFile(&entry);\r
+ break;\r
+ }\r
+ } while(entry.findNext());\r
+ }\r
+ entry.freeEntry();\r
+}\r
+/**\r
+ * Processes a directory tree.\r
+ *\r
+ * Finds all filtered files in this directory and its subdirs and call <code>processFile()</code>\r
+ * or <code>processDir()</code>.\r
+ *\r
+ * @param directory the name of the directory\r
+ */\r
+void ReTool::processTree(const char* directory){\r
+ m_traverser.changeBase(directory);\r
+ setFilterFromProgramArgs(m_filter);\r
+ m_traverser.setPropertiesFromFilter(&m_filter);\r
+ ReDirStatus_t* entry;\r
+ int level;\r
+ while( (entry = m_traverser.nextFile(level, &m_filter)) != NULL){\r
+ if (entry->isDirectory())\r
+ processDir(entry);\r
+ else\r
+ processFile(entry);\r
+ }\r
+}\r
+/**\r
+ * Processes one file.\r
+ *\r
+ * Normally this method will be overwritten.\r
+ *\r
+ * @param entry the properties of the file to process\r
+ */\r
+void ReTool::processFile(ReDirStatus_t* entry){\r
+ fprintf(m_output, "+++ ignored (not a directory): %s\n", entry->fullName());\r
+}\r
+/**\r
+ * Processes one directory.\r
+ *\r
+ * Normally this method will be overwritten.\r
+ *\r
+ * @param entry the properties of the directory to process\r
+ */\r
+void ReTool::processDir(ReDirStatus_t* entry){\r
+ fprintf(m_output, "+++ ignored (not a file): %s\n", entry->fullName());\r
+}\r
+\r
/**\r
* Constructor.\r
*/\r
ReDirStatisticData::ReDirStatisticData() :\r
- m_sizes(0),\r
- m_files(0),\r
- m_dirs(0),\r
+ ReDirTreeStatistic(),\r
m_path()\r
{\r
}\r
* @param source the source to copy\r
*/\r
ReDirStatisticData::ReDirStatisticData(const ReDirStatisticData& source) :\r
- m_sizes(source.m_sizes),\r
- m_files(source.m_files),\r
- m_dirs(source.m_dirs),\r
m_path(source.m_path)\r
{\r
}\r
ReDirStatisticData& ReDirStatisticData::operator =(const ReDirStatisticData& source){\r
m_sizes = source.m_sizes;\r
m_files = source.m_files;\r
- m_dirs = source.m_dirs;\r
+ m_directories = source.m_directories;\r
m_path = source.m_path;\r
return *this;\r
}\r
* Constructor.\r
*/\r
ReDirStatistic::ReDirStatistic(int deltaList, int deltaBuffer) :\r
- ReDirOptions(s_statisticUsage, s_statisticExamples),\r
- m_list(deltaList, deltaBuffer),\r
- m_traceInterval(0),\r
- m_lastTrace(0)\r
+ ReTool(s_statisticUsage, s_statisticExamples, 2, 0, 1, false),\r
+ m_list(deltaList, deltaBuffer)\r
{\r
// standard short options: D d O o P p T t v y Z z\r
m_programArgs.addBool("kbyte", \r
ReDirStatisticData& ReDirStatisticData::add(const ReDirStatisticData& source){\r
m_sizes += source.m_sizes;\r
m_files += source.m_files;\r
- m_dirs += source.m_dirs;\r
+ m_directories += source.m_directories;\r
return *this;\r
}\r
/**\r
* Initializes the data of the instance.\r
*/\r
void ReDirStatisticData::clear(){\r
- m_sizes = 0;\r
- m_files = 0;\r
- m_dirs = 0;\r
+ ReDirTreeStatistic::clear();\r
m_path.setLength(0);\r
}\r
+/**\r
+ * Constructor.\r
+ */\r
+ReDirBatch::ReDirBatch() :\r
+ ReTool(s_batchUsage, s_batchExamples, 0, 0, 0, true),\r
+ m_arguments(),\r
+ m_script(),\r
+ m_isExe(false)\r
+{\r
+ // standard short options: D d O o P p T t v y Z z\r
+ m_programArgs.addString("first",\r
+ i18n("defines the first line of the output"),\r
+ '1', "first-line", true,\r
+#if defined __linux__\r
+ "#! /bin/sh"\r
+#elif defined __WIN32__\r
+ "rem this batch is created by dirtool"\r
+#endif\r
+ );\r
+ m_programArgs.addString("arguments",\r
+ i18n("template for the output line.\n"\r
+ "Possible placeholders: (e.g. e:\\data\\sample.txt)\n"\r
+ " !full!: e:\\data\\sample.txt\n"\r
+ " !path!: e:\\data\\\n"\r
+ " !basename!: sample.txt\n"\r
+ " !name!: sample\n"\r
+ " !ext!: .txt\n"\r
+ "example: --arguments='echo !basename! in !path! found'"),\r
+ 'a', "arguments", false, NULL);\r
+ m_programArgs.addString("script",\r
+ i18n("name of the script (starts each output line)"),\r
+ 'c', "script", false, NULL);\r
+#if defined __WIN32__\r
+ m_programArgs.addBool("isexe",\r
+ i18n("supresses the starting 'call' of each output line"\r
+ "neccessary if a *.exe will be called (instead of a *.bat)"),\r
+ 'x', "is-exe", false);\r
+#endif\r
+ addStandardFilterOptions();\r
+}\r
+\r
+static void replaceMakros(const char* arguments, ReDirStatus_t* entry, const char* delim, ReByteBuffer& line){\r
+ line.set(arguments, -1);\r
+ // we prepare the removal of unwanted delimiters in constructed placeholders:\r
+ // example: !path!!name!: without correction: "e:\\data\\""xxx"\r
+ // We want: "e:\\data\\xxx"\r
+ line.replaceAll("!!", 2, "!\x01!", 3);\r
+ ReByteBuffer replacement;\r
+ if (strstr(arguments, "!full!") != NULL){\r
+ replacement.set(delim, -1).append(entry->m_path);\r
+ replacement.append(entry->node(), -1).append(delim, -1);\r
+ line.replaceAll("!full!", 6, replacement.str(), replacement.length());\r
+ }\r
+ if (strstr(arguments, "!path!") != NULL){\r
+ replacement.set(delim, -1).append(entry->m_path).append(delim, -1);\r
+ line.replaceAll("!path!", 6, replacement.str(), replacement.length());\r
+ }\r
+ if (strstr(arguments, "!basename!") != NULL){\r
+ replacement.set(delim, -1).append(entry->node(), -1).append(delim, -1);\r
+ line.replaceAll("!basename!", 10, replacement.str(), replacement.length());\r
+ }\r
+ if (strstr(arguments, "!name!") != NULL){\r
+ replacement.set(delim, -1).append(entry->node(), -1);\r
+ int ix = replacement.rindexOf(".", 1);\r
+ if (ix > 1)\r
+ replacement.setLength(ix);\r
+ replacement.append(delim, -1);\r
+ line.replaceAll("!name!", 6, replacement.str(), replacement.length());\r
+ }\r
+ if (strstr(arguments, "!ext!") != NULL){\r
+ replacement.set(delim, -1).append(entry->node(), -1);\r
+ int ix = replacement.rindexOf(".", 1);\r
+ if (ix > 1)\r
+ replacement.remove(1, ix - 1);\r
+ else\r
+ replacement.setLength(1);\r
+ replacement.append(delim, -1);\r
+ line.replaceAll("!ext!", 5, replacement.str(), replacement.length());\r
+ }\r
+ // We remove the unwanted delimiters (see above):\r
+ ReByteBuffer buffer;\r
+ buffer.set(delim, -1).append("\x01", 1).append(delim, -1);\r
+ line.replaceAll(buffer.str(), buffer.length(), "", 0);\r
+}\r
+/**\r
+ * Creates the batch file.\r
+ */\r
+void ReDirBatch::doIt(){\r
+ ReByteBuffer buffer;\r
+ m_arguments.append(m_programArgs.getString("arguments", buffer), -1);\r
+ m_script.append(m_programArgs.getString("script", buffer), -1);\r
+ if (m_arguments.length() + m_script.length() == 0)\r
+ help(i18n("one of the option must be set: -a (--arguments) or -c (--script)"));\r
+#if defined __WIN32__\r
+ m_isExe = m_programArgs.getBool("isexe");\r
+#endif\r
+ processFileArguments();\r
+ if (m_verboseLevel >= V_SUMMARY){\r
+ int duration = int(time(NULL) - m_start);\r
+#if defined __linux__\r
+ const char* prefix = "#";\r
+#elif defined __WIN32__\r
+ const char* prefix = "rem";\r
+#endif\r
+ toString(buffer);\r
+ buffer.append(" ").appendTime(duration);\r
+ fprintf(m_output, "%s %s\n", buffer.str());\r
+ }\r
+}\r
+\r
+/**\r
+ * Processes one directory.\r
+ *\r
+ * @param entry the properties of the directory to process\r
+ */\r
+void ReDirBatch::processDir(ReDirStatus_t* entry){\r
+ processFile(entry);\r
+}\r
+\r
+/**\r
+ * Processes one file.\r
+ *\r
+ * @param entry the properties of the file to process\r
+ */\r
+void ReDirBatch::processFile(ReDirStatus_t* entry){\r
+ ReByteBuffer line;\r
+#if defined __linux__\r
+ static const char* delim = "'";\r
+#elif defined __WIN32__\r
+ static const char* delim = "\"";\r
+#endif\r
+ if (m_script.length() > 0){\r
+#if defined __WIN32__\r
+ if (! m_isExe)\r
+ line.append("call ");\r
+#endif\r
+ line.append(m_script).append(" ").append(delim, -1);\r
+ line.append(entry->m_path).append(entry->node(), -1);\r
+ line.append(delim, -1);\r
+ } else {\r
+ replaceMakros(m_arguments.str(), entry, delim, line);\r
+ }\r
+ fprintf(m_output, "%s\n", line.str());\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ */\r
+ReDirList::ReDirList() :\r
+ ReTool(s_listUsage, s_listExamples, 0, 0, 0, true),\r
+ m_shortFormat(false)\r
+{\r
+ m_programArgs.addBool("short", i18n("output is only path and basename"),\r
+ '1', "--short", false);\r
+ addStandardFilterOptions();\r
+}\r
+\r
+/**\r
+ * Lists the metadata of the specified files.\r
+ */\r
+void ReDirList::doIt(){\r
+ m_shortFormat = m_programArgs.getBool("short");\r
+ processFileArguments();\r
+ if (m_verboseLevel >= V_SUMMARY){\r
+ int duration = int(time(NULL) - m_start);\r
+ ReByteBuffer line;\r
+ toString(line);\r
+ line.appendTime(duration).append(" ", 1).append(i18n("sec"));\r
+ fprintf(m_output, "=== %s\n", line.str());\r
+ }\r
+}\r
+\r
+/**\r
+ * Processes one directory.\r
+ *\r
+ * @param entry the properties of the directory to process\r
+ */\r
+void ReDirList::processDir(ReDirStatus_t* entry){\r
+ processFile(entry);\r
+}\r
+/**\r
+ * Processes one file.\r
+ *\r
+ * @param entry the properties of the file to process\r
+ */\r
+void ReDirList::processFile(ReDirStatus_t* entry){\r
+ ReByteBuffer bufferRights;\r
+ ReByteBuffer bufferTime;\r
+ if (m_shortFormat)\r
+ fprintf(m_output, "%s%s\n", entry->m_path.str(), entry->node());\r
+ else\r
+ fprintf(m_output, "%s %12.6f %s %02x %s%s\n",\r
+ entry->rightsAsString(bufferRights),\r
+ entry->fileSize() / 1E6,\r
+ entry->filetimeAsString(bufferTime),\r
+ entry->type(),\r
+ entry->m_path.str(), entry->node());\r
+}\r
+\r
\r
/**\r
* Calculates the statistic of a directory tree.\r
}\r
}\r
if (entry->isDirectory()){\r
- current->m_dirs++;\r
+ current->m_directories++;\r
} else if (! useFilter || filter.match(*entry)){\r
current->m_sizes += entry->fileSize();\r
current->m_files++;\r
* @param arc count of arguments in <code>argv</code>\r
* @param argv the program arguments.\r
*/\r
-void ReDirStatistic::run(int argc, const char* argv[]){\r
- time_t start = time(NULL);\r
- try {\r
- m_programArgs.init(argc, argv);\r
- if (m_programArgs.getArgCount() < 1)\r
- m_programArgs.help("statistic: missing path", false, stdout);\r
- int depth = 1;\r
- if (m_programArgs.getArgCount() > 1){\r
- const char* arg1 = m_programArgs.getArg(1);\r
- if (ReStringUtils::lengthOfUnsigned(arg1, -1, (unsigned *) &depth) == 0)\r
- m_programArgs.help("depth is not an integer", false, stdout);\r
- }\r
- void (*proc) (const ReDirStatisticData& data,\r
- ReDirStatistic& parent, ReByteBuffer& line) = &formatWithSizeFilesAndDirs;\r
- if (m_programArgs.getBool("kbyte"))\r
- proc = &formatLikeDu;\r
- const ReStringList& list = calculate(m_programArgs.getArg(0), depth, proc);\r
- ReByteBuffer buffer;\r
- for (size_t ix = 0; ix < list.count(); ix++){\r
- buffer.set(list.strOf(ix), list.strLengthOf(ix));\r
- fprintf(m_output, "%s\n", buffer.str());\r
- }\r
- if (m_verboseLevel >= V_SUMMARY){\r
- int duration = int(time(NULL) - start);\r
- fprintf(m_output, "=== duration: ");\r
- if (duration >= 3600)\r
- fprintf(m_output, "%d:", duration / 3600);\r
- fprintf(m_output, "%02d:%02d\n", duration % 3600 / 60, duration % 60);\r
- }\r
- } catch (ReOptionException& exc) {\r
- m_programArgs.help(exc.getMessage(), false, stdout);\r
- }\r
+void ReDirStatistic::doIt(){\r
+ int depth = 1;\r
+ if (m_programArgs.getArgCount() > 1){\r
+ const char* arg1 = m_programArgs.getArg(1);\r
+ if (ReStringUtils::lengthOfUnsigned(arg1, -1, (unsigned *) &depth) == 0)\r
+ m_programArgs.help("depth is not an integer", false, stdout);\r
+ }\r
+ void (*proc) (const ReDirStatisticData& data,\r
+ ReDirStatistic& parent, ReByteBuffer& line) = &formatWithSizeFilesAndDirs;\r
+ if (m_programArgs.getBool("kbyte"))\r
+ proc = &formatLikeDu;\r
+ const ReStringList& list = calculate(m_programArgs.getArg(0), depth, proc);\r
+ ReByteBuffer buffer;\r
+ for (size_t ix = 0; ix < list.count(); ix++){\r
+ buffer.set(list.strOf(ix), list.strLengthOf(ix));\r
+ fprintf(m_output, "%s\n", buffer.str());\r
+ }\r
+ if (m_verboseLevel >= V_SUMMARY){\r
+ int duration = int(time(NULL) - m_start);\r
+ fprintf(m_output, "=== duration: ");\r
+ if (duration >= 3600)\r
+ fprintf(m_output, "%d:", duration / 3600);\r
+ fprintf(m_output, "%02d:%02d\n", duration % 3600 / 60, duration % 60);\r
+ }\r
}\r
+\r
/**\r
* Formats a line like the du (disk usage) command.\r
*\r
// Round up to the next KiByte:\r
char buffer[256];\r
_snprintf(buffer, sizeof buffer, "%14.6f MB %7d %7d\t",\r
- data.m_sizes / 1E6, data.m_files, data.m_dirs);\r
+ data.m_sizes / 1E6, data.m_files, data.m_directories);\r
line.append(buffer, -1).append(data.m_path);\r
}\r
+/**\r
+ * Constructor.\r
+ */\r
+ReDirTouch::ReDirTouch() :\r
+ ReTool(s_touchUsage, s_touchExamples, 2, 1, 0, false),\r
+ m_buffer(),\r
+ m_properties()\r
+{\r
+ // standard short options: D d O o P p T t v y Z z\r
+ m_programArgs.addString("accessed",\r
+ i18n("the new access time.\n"\r
+ "Formats: absolute, relative to now, relative to the current filetime\n"\r
+ "[yyyy.mm.dd/]HH:MM:SS \n"\r
+ "now-<count>{s|m|h|d}\n"\r
+ "{+|-}<count>{s|m|h|d}"),\r
+ 'a', "--accessed", false, NULL);\r
+ m_programArgs.addString("modified",\r
+ i18n("the new modification time.\n"\r
+ "Formats: absolute, relative to now, relative to the current filetime\n"\r
+ "[yyyy.mm.dd/]HH:MM:SS\n"\r
+ "now-<count>{s|m|h|d}\n"\r
+ "{+|-}<count>{s|m|h|d}"),\r
+ 'm', "--modified", false, NULL);\r
+ addStandardFilterOptions();\r
+}\r
+/**\r
+ * Sets the filetime for the specified files.\r
+ */\r
+void ReDirTouch::doIt(){\r
+ ReByteBuffer buffer;\r
+ if (m_programArgs.getString("modified", buffer)[0] != '\0')\r
+ m_modified = checkDate(buffer.str());\r
+ if (m_programArgs.getString("accessed", buffer)[0] != '\0')\r
+ m_accessed = checkDate(buffer.str());\r
+ processFileArguments();\r
+ if (m_verboseLevel >= V_SUMMARY){\r
+ int duration = int(time(NULL) - m_start);\r
+ ReByteBuffer line;\r
+ toString(line);\r
+ line.appendTime(duration).append(" ", 1).append(i18n("sec"));\r
+ fprintf(m_output, "=== %s\n", line.str());\r
+ }\r
+}\r
+\r
+void ReDirTouch::processDir(ReDirStatus_t* entry){\r
+ processFile(entry);\r
+}\r
+void ReDirTouch::processFile(ReDirStatus_t* entry){\r
+\r
+}\r
+\r
+/**\r
+ * Sets file times.\r
+ *\r
+ * @param filename the name of the file\r
+ * @param properties contains modification and access time\r
+ * @param logger NULL or the logger\r
+ */\r
+bool ReDirTouch::touch(const char* filename, ReFileProperties_t* properties,\r
+ ReLogger* logger){\r
+}\r
+\r
+\r
+\r
/**\r
* Prints a vector of lines.\r
* \r
}\r
\r
/**\r
- * Prints an message how to use the statistic module and exits.\r
+ * Prints a message how to use the module and exits.\r
*/\r
-void ReDirTools::statisticUsage(){\r
- ReDirStatistic statistic;\r
- statistic.programArgs().help(NULL, false, stdout);\r
+void ReDirTools::usage(ReTool& tool){\r
+ tool.programArgs().help(NULL, false, stdout);\r
}\r
\r
/**\r
*/\r
void ReDirTools::usage(const char* msg, const char* msg2){\r
printf ("Version: %s\n", m_version);\r
- printf ("usage: dirtool <command> <opt>\n");\r
- statisticUsage();\r
+ printf ("usage: dirtool <command> <opt>\n"\r
+ "call 'dirtool help' for more info\n");\r
if (msg != NULL)\r
printf ("+++ %s%s\n", msg, msg2 == NULL ? "" : msg2);\r
exit(1);\r
}\r
\r
-/**\r
- * Constructor.\r
- */\r
-ReDirList::ReDirList() :\r
- ReTool(s_listUsage, s_listExamples)\r
-{\r
- m_programArgs.addBool("short", i18n("output is only path and basename"),\r
- '1', "--short", false);\r
- addStandardFilterOptions();\r
-}\r
-\r
-/**\r
- * Gets the arguments for the "list" command and execute this.\r
- *\r
- * @param argc the number of arguments\r
- * @param argav the argument vector\r
- */\r
-void ReDirList::list(int argc, const char* argv[]){\r
- ReDirEntryFilter_t filter;\r
- try {\r
- time_t start = time(NULL);\r
- m_programArgs.init(argc, argv);\r
- bool shortOutput = m_programArgs.getBool("short");\r
- setFilterFromProgramArgs(filter);\r
- bool noPath = m_programArgs.getArgCount() == 0;\r
- ReByteBuffer bufferRights;\r
- ReByteBuffer bufferTime;\r
- int64_t sumSizes = 0;\r
- int files = 0;\r
- int dirs = 0;\r
- \r
- for (int ix = 0; noPath || ix < m_programArgs.getArgCount(); ix++){\r
- ReTraverser traverser(noPath ? "." : m_programArgs.getArg(ix));\r
- noPath = false;\r
- traverser.setPropertiesFromFilter(&filter);\r
- int level;\r
- ReDirStatus_t* entry;\r
- while( (entry = traverser.nextFile(level, &filter)) != NULL){\r
- if (entry->isDirectory())\r
- dirs++;\r
- else{\r
- files++;\r
- sumSizes += entry->fileSize();\r
- }\r
- if (! printOneFile(entry)){\r
- if (shortOutput)\r
- fprintf(m_output, "%s%s\n", entry->m_path.str(), entry->node());\r
- else\r
- fprintf(m_output, "%s %12.6f %s %02x %s%s\n",\r
- entry->rightsAsString(bufferRights), \r
- entry->fileSize() / 1E6, \r
- entry->filetimeAsString(bufferTime), \r
- entry->type(),\r
- entry->m_path.str(), entry->node());\r
- }\r
- }\r
- }\r
- if (m_verboseLevel >= V_SUMMARY){\r
- int duration = int(time(NULL) - start);\r
- fprintf(m_output, "+++ %d dirs and %d file(s) with %.6f MByte in %02d:%02d sec\n",\r
- dirs, files, sumSizes / 1E6, duration / 60, duration % 60);\r
- }\r
- } catch(ReOptionException& exc){\r
- help(exc.getMessage());\r
- }\r
-}\r
-\r
-/**\r
- * Constructor.\r
- */\r
-ReDirBatch::ReDirBatch() :\r
- ReTool(s_batchUsage, s_batchExamples)\r
-{\r
- // standard short options: D d O o P p T t v y Z z\r
- m_programArgs.addString("first",\r
- i18n("defines the first line of the output"),\r
- '1', "first-line", true,\r
-#if defined __linux__\r
- "#! /bin/sh"\r
-#elif defined __WIN32__\r
- "rem this batch is created by dirtool"\r
-#endif\r
- );\r
- m_programArgs.addString("arguments", \r
- i18n("template for the output line.\n"\r
- "Possible placeholders: (e.g. e:\\data\\sample.txt)\n"\r
- " !full!: e:\\data\\sample.txt\n"\r
- " !path!: e:\\data\\\n"\r
- " !basename!: sample.txt\n"\r
- " !name!: sample\n"\r
- " !ext!: .txt\n"\r
- "example: --arguments='echo !basename! in !path! found'"),\r
- 'a', "arguments", false, NULL);\r
- m_programArgs.addString("script",\r
- i18n("name of the script (starts each output line)"),\r
- 'c', "script", false, NULL);\r
-#if defined __WIN32__\r
- m_programArgs.addBool("isexe",\r
- i18n("supresses the starting 'call' of each output line"\r
- "neccessary if a *.exe will be called (instead of a *.bat)"),\r
- 'x', "is-exe", false);\r
-#endif\r
- addStandardFilterOptions();\r
-}\r
-\r
-static void replaceMakros(const char* arguments, ReDirStatus_t* entry, const char* delim, ReByteBuffer& line){\r
- line.set(arguments, -1);\r
- // we prepare the removal of unwanted delimiters in constructed placeholders:\r
- // example: !path!!name!: without correction: "e:\\data\\""xxx"\r
- // We want: "e:\\data\\xxx"\r
- line.replaceAll("!!", 2, "!\x01!", 3);\r
- ReByteBuffer replacement;\r
- if (strstr(arguments, "!full!") != NULL){\r
- replacement.set(delim, -1).append(entry->m_path);\r
- replacement.append(entry->node(), -1).append(delim, -1);\r
- line.replaceAll("!full!", 6, replacement.str(), replacement.length());\r
- }\r
- if (strstr(arguments, "!path!") != NULL){\r
- replacement.set(delim, -1).append(entry->m_path).append(delim, -1);\r
- line.replaceAll("!path!", 6, replacement.str(), replacement.length());\r
- }\r
- if (strstr(arguments, "!basename!") != NULL){\r
- replacement.set(delim, -1).append(entry->node(), -1).append(delim, -1);\r
- line.replaceAll("!basename!", 10, replacement.str(), replacement.length());\r
- }\r
- if (strstr(arguments, "!name!") != NULL){\r
- replacement.set(delim, -1).append(entry->node(), -1);\r
- int ix = replacement.rindexOf(".", 1);\r
- if (ix > 1)\r
- replacement.setLength(ix);\r
- replacement.append(delim, -1);\r
- line.replaceAll("!name!", 6, replacement.str(), replacement.length());\r
- }\r
- if (strstr(arguments, "!ext!") != NULL){\r
- replacement.set(delim, -1).append(entry->node(), -1);\r
- int ix = replacement.rindexOf(".", 1);\r
- if (ix > 1)\r
- replacement.remove(1, ix - 1);\r
- else\r
- replacement.setLength(1);\r
- replacement.append(delim, -1);\r
- line.replaceAll("!ext!", 5, replacement.str(), replacement.length());\r
- }\r
- // We remove the unwanted delimiters (see above):\r
- ReByteBuffer buffer;\r
- buffer.set(delim, -1).append("\x01", 1).append(delim, -1);\r
- line.replaceAll(buffer.str(), buffer.length(), "", 0);\r
-}\r
-/**\r
- * Gets the arguments for the "list" command and execute this.\r
- *\r
- * @param argc the number of arguments\r
- * @param argav the argument vector\r
- */\r
-void ReDirBatch::createBatch(int argc, const char* argv[]){\r
- ReDirEntryFilter_t filter;\r
- try {\r
- time_t start = time(NULL);\r
- m_programArgs.init(argc, argv);\r
- ReByteBuffer buffer;\r
- ReByteBuffer arguments(m_programArgs.getString("arguments", buffer), -1);\r
- ReByteBuffer script(m_programArgs.getString("script", buffer), -1);\r
- if (arguments.length() + script.length() == 0)\r
- help(i18n("one of the option must be set: -a (--arguments) or -c (--script)"));\r
-#if defined __WIN32__\r
- bool isExe = m_programArgs.getBool("isexe");\r
-#endif\r
- setFilterFromProgramArgs(filter);\r
- if (m_programArgs.getArgCount() == 0)\r
- help(i18n("no arguments given (missing path)"));\r
- if (m_programArgs.getString("first", buffer)[0] != '\0')\r
- printf("%s\n", buffer.str());\r
- int64_t sumSizes = 0;\r
- int files = 0;\r
- int dirs = 0;\r
-#if defined __linux__\r
- const char* delim = "'";\r
-#elif defined __WIN32__\r
- const char* delim = "\"";\r
-#endif\r
- for (int ix = 0; ix < m_programArgs.getArgCount(); ix++){\r
- ReTraverser traverser(m_programArgs.getArg(ix));\r
- traverser.setPropertiesFromFilter(&filter);\r
- int level;\r
- ReDirStatus_t* entry;\r
- ReByteBuffer line;\r
- while( (entry = traverser.nextFile(level, &filter)) != NULL){\r
- if (entry->isDirectory())\r
- dirs++;\r
- else{\r
- files++;\r
- sumSizes += entry->fileSize();\r
- }\r
- if (script.length() > 0){\r
- line.setLength(0);\r
-#if defined __WIN32__\r
- if (! isExe)\r
- line.append("call ");\r
-#endif\r
- line.append(script).append(" ").append(delim, -1);\r
- line.append(entry->m_path).append(entry->node(), -1);\r
- line.append(delim, -1);\r
- } else {\r
- replaceMakros(arguments.str(), entry, delim, line);\r
- }\r
- fprintf(m_output, "%s\n", line.str());\r
- }\r
- }\r
- if (m_verboseLevel >= V_SUMMARY){\r
- int duration = int(time(NULL) - start);\r
-#if defined __linux__\r
- const char* prefix = "#";\r
-#elif defined __WIN32__\r
- const char* prefix = "rem";\r
-#endif\r
- fprintf(m_output, "%s %d dir(s) and %d file(s) with %.6f MByte in %02d:%02d sec\n",\r
- prefix, dirs, files, sumSizes / 1E6, duration / 60, duration % 60);\r
- }\r
- } catch(ReOptionException& exc){\r
- help(exc.getMessage());\r
- }\r
-}\r
-\r
/**\r
* creates a subdirectory (and the parent directories if neccessary.\r
*\r
* Constructor.\r
*/\r
ReDirSync::ReDirSync() :\r
- ReTool(s_syncUsage, s_syncExamples),\r
+ ReTool(s_syncUsage, s_syncExamples, 2, 0, 1, false),\r
m_buffer()\r
{\r
// standard short options: D d O o P p T t v y Z z\r
}\r
\r
/**\r
- * Gets the arguments for the "list" command and execute this.\r
- *\r
- * @param argc the number of arguments\r
- * @param argav the argument vector\r
+ * Synchronizes two directory trees.\r
*/\r
-void ReDirSync::synchronize(int argc, const char* argv[]){\r
+void ReDirSync::doIt(){\r
ReDirEntryFilter_t filter;\r
const char* sep = OS_SEPARATOR;\r
struct stat info;\r
- try {\r
- time_t start = time(NULL);\r
- m_programArgs.init(argc, argv);\r
- ReByteBuffer buffer;\r
- if (m_programArgs.getArgCount() < 2)\r
- help(i18n("missing argument(s) (source / target)"));\r
- ReByteBuffer target(m_programArgs.getArg(m_programArgs.getArgCount() - 1));\r
- if (target.endsWith(sep, 1))\r
- target.setLength(target.length() - 1);\r
- if (stat(target.str(), &info) != 0)\r
- help(i18n("target does not exist: $1"), target.str());\r
- else if (! S_ISDIR(info.st_mode))\r
- help(i18n("target is not a directory: $1"), target.str());\r
- size_t lengthTargetBase = target.length();\r
- bool addOnly = m_programArgs.getBool("add");\r
- int maxFileTimeDiff = m_programArgs.getInt("timediff");\r
- bool dry = m_programArgs.getBool("dry");\r
- bool ignoreDate = m_programArgs.getBool("ignoredate");\r
- bool mustExist = m_programArgs.getBool("mustexist");\r
- setFilterFromProgramArgs(filter);\r
- int64_t sumSizes = 0;\r
- int files = 0;\r
- int treeFiles = 0;\r
- int treeDirs = 0;\r
- int64_t treeSumSizes = 0ll;\r
- ReByteBuffer source, targetFile;\r
- for (int ix = 0; ix < m_programArgs.getArgCount() - 1; ix++){\r
- source.set(m_programArgs.getArg(ix), -1);\r
- target.setLength(lengthTargetBase);\r
- bool endsWithSlash = source.endsWith(sep, 1);\r
- if (endsWithSlash)\r
- source.setLength(source.length() - 1);\r
- if (stat(source.str(), &info) != 0)\r
- help(i18n("source does not exist: $1"), source.str());\r
- else if (! S_ISDIR(info.st_mode))\r
- help(i18n("source is not a directory: $1"), source.str());\r
- if (! endsWithSlash){\r
- // the basename of the source will be appended to the target:\r
- int startNode = source.rindexOf(sep, 1, 0, source.length() - 1);\r
- target.append(OS_SEPARATOR, 1);\r
- target.append(source.str() + startNode + 1, -1);\r
- }\r
- size_t ixSourceRelative = source.length();\r
- size_t ixTargetRelative = target.length();\r
+ ReByteBuffer buffer;\r
+ ReByteBuffer target(m_programArgs.getArg(m_programArgs.getArgCount() - 1));\r
+ if (target.endsWith(sep, 1))\r
+ target.setLength(target.length() - 1);\r
+ if (stat(target.str(), &info) != 0)\r
+ help(i18n("target does not exist: $1"), target.str());\r
+ else if (! S_ISDIR(info.st_mode))\r
+ help(i18n("target is not a directory: $1"), target.str());\r
+ size_t lengthTargetBase = target.length();\r
+ bool addOnly = m_programArgs.getBool("add");\r
+ int maxFileTimeDiff = m_programArgs.getInt("timediff");\r
+ bool dry = m_programArgs.getBool("dry");\r
+ bool ignoreDate = m_programArgs.getBool("ignoredate");\r
+ bool mustExist = m_programArgs.getBool("mustexist");\r
+ setFilterFromProgramArgs(filter);\r
+ int64_t sumSizes = 0;\r
+ int files = 0;\r
+ int treeFiles = 0;\r
+ int treeDirs = 0;\r
+ int64_t treeSumSizes = 0ll;\r
+ ReByteBuffer source, targetFile;\r
+ for (int ix = 0; ix < m_programArgs.getArgCount() - 1; ix++){\r
+ source.set(m_programArgs.getArg(ix), -1);\r
+ target.setLength(lengthTargetBase);\r
+ bool endsWithSlash = source.endsWith(sep, 1);\r
+ if (endsWithSlash)\r
+ source.setLength(source.length() - 1);\r
+ if (stat(source.str(), &info) != 0)\r
+ help(i18n("source does not exist: $1"), source.str());\r
+ else if (! S_ISDIR(info.st_mode))\r
+ help(i18n("source is not a directory: $1"), source.str());\r
+ if (! endsWithSlash){\r
+ // the basename of the source will be appended to the target:\r
+ int startNode = source.rindexOf(sep, 1, 0, source.length() - 1);\r
+ target.append(OS_SEPARATOR, 1);\r
+ target.append(source.str() + startNode + 1, -1);\r
+ }\r
+ size_t ixSourceRelative = source.length();\r
+ size_t ixTargetRelative = target.length();\r
\r
- ReTraverser traverser(source.str());\r
- traverser.setPropertiesFromFilter(&filter);\r
- int level;\r
- ReDirStatus_t* entry;\r
- ReByteBuffer line;\r
- while( (entry = traverser.nextFile(level, &filter)) != NULL){\r
- if (entry->isDirectory())\r
+ ReTraverser traverser(source.str());\r
+ traverser.setPropertiesFromFilter(&filter);\r
+ int level;\r
+ ReDirStatus_t* entry;\r
+ ReByteBuffer line;\r
+ while( (entry = traverser.nextFile(level, &filter)) != NULL){\r
+ if (entry->isDirectory())\r
+ continue;\r
+ // append the new relative path from source to target:\r
+ target.setLength(ixTargetRelative);\r
+ target.append(entry->m_path.str() + ixSourceRelative, -1);\r
+ if (stat(target.str(), &info) != 0)\r
+ makeDirWithParents(target, ixTargetRelative, traverser);\r
+ targetFile.set(target).append(entry->node(), -1);\r
+ const char* targetRelativePath = targetFile.str() + ixTargetRelative + 1;\r
+ bool exists = stat(targetFile.str(), &info) == 0;\r
+ if (! exists && mustExist){\r
+ if (m_verboseLevel == V_CHATTER)\r
+ fprintf(m_output, "-ignored: %s does not exist\n", targetRelativePath);\r
+ continue;\r
+ }\r
+ if (exists){\r
+ if (addOnly){\r
+ if (m_verboseLevel >= V_CHATTER)\r
+ fprintf(m_output, "~ignored: %s exists\n", targetRelativePath);\r
continue;\r
- // append the new relative path from source to target:\r
- target.setLength(ixTargetRelative);\r
- target.append(entry->m_path.str() + ixSourceRelative, -1);\r
- if (stat(target.str(), &info) != 0)\r
- makeDirWithParents(target, ixTargetRelative, traverser);\r
- targetFile.set(target).append(entry->node(), -1);\r
- const char* targetRelativePath = targetFile.str() + ixTargetRelative + 1;\r
- bool exists = stat(targetFile.str(), &info) == 0;\r
- if (! exists && mustExist){\r
- if (m_verboseLevel == V_CHATTER)\r
- fprintf(m_output, "-ignored: %s does not exist\n", targetRelativePath);\r
+ }\r
+ if (ignoreDate && entry->fileSize() == info.st_size){\r
+ if (m_verboseLevel >= V_CHATTER)\r
+ fprintf(m_output, "_ignored: %s same size\n", targetRelativePath);\r
continue;\r
}\r
- if (exists){\r
- if (addOnly){\r
- if (m_verboseLevel >= V_CHATTER)\r
- fprintf(m_output, "~ignored: %s exists\n", targetRelativePath);\r
- continue;\r
- }\r
- if (ignoreDate && entry->fileSize() == info.st_size){\r
- if (m_verboseLevel >= V_CHATTER)\r
- fprintf(m_output, "_ignored: %s same size\n", targetRelativePath);\r
- continue;\r
- }\r
- // target younger than source?\r
- int diff = int(info.st_mtime - entry->filetimeToTime(entry->modified()));\r
- if (! ignoreDate && info.st_mtime - entry->filetimeToTime(entry->modified())\r
- <= maxFileTimeDiff) {\r
- if (m_verboseLevel >= V_CHATTER)\r
- fprintf(m_output, "=ignored: %s same time\n", targetRelativePath);\r
- continue;\r
- }\r
+ // target younger than source?\r
+ int diff = int(info.st_mtime - entry->filetimeToTime(entry->modified()));\r
+ if (! ignoreDate && info.st_mtime - entry->filetimeToTime(entry->modified())\r
+ <= maxFileTimeDiff) {\r
+ if (m_verboseLevel >= V_CHATTER)\r
+ fprintf(m_output, "=ignored: %s same time\n", targetRelativePath);\r
+ continue;\r
}\r
- files++;\r
- sumSizes += entry->fileSize();\r
- if (m_verboseLevel >= V_NORMAL)\r
- fprintf(m_output, "%c%s%s\n", exists ? '!' : '+', targetRelativePath,\r
- dry ? " would be copied" : "");\r
- if (! dry)\r
- copyFile(entry, targetFile.str());\r
}\r
- treeFiles += traverser.files();\r
- treeDirs += traverser.directories();\r
- treeSumSizes+= traverser.sizes();\r
- }\r
- if (m_verboseLevel >= V_SUMMARY){\r
- int duration = int(time(NULL) - start);\r
- fprintf(m_output, i18n(\r
- "=== copied: %02d:%02d sec %7d file(s) %12.6f MByte (%.3f MB/sec).\n"\r
- "=== tree : %5d dir(s) %7d file(s) %12.6f MByte\n"),\r
- duration / 60, duration % 60, files, sumSizes / 1E6, \r
- sumSizes / 1E6 / (duration == 0 ? 1 : duration),\r
- treeDirs, treeFiles, treeSumSizes / 1E6);\r
- }\r
- } catch(ReOptionException& exc){\r
- help(exc.getMessage());\r
- }\r
-}\r
-\r
-/**\r
- * Gets the arguments for the "batch" command and execute this.\r
- *\r
- * @param argc the number of arguments\r
- * @param argav the argument vector\r
- */\r
-void ReDirTools::batch(int argc, const char* argv[]){\r
- ReDirBatch batch;\r
- batch.createBatch(argc, argv);\r
+ files++;\r
+ sumSizes += entry->fileSize();\r
+ if (m_verboseLevel >= V_NORMAL)\r
+ fprintf(m_output, "%c%s%s\n", exists ? '!' : '+', targetRelativePath,\r
+ dry ? " would be copied" : "");\r
+ if (! dry)\r
+ copyFile(entry, targetFile.str());\r
+ }\r
+ treeFiles += traverser.files();\r
+ treeDirs += traverser.directories();\r
+ treeSumSizes+= traverser.sizes();\r
+ }\r
+ if (m_verboseLevel >= V_SUMMARY){\r
+ int duration = int(time(NULL) - m_start);\r
+ fprintf(m_output, i18n(\r
+ "=== copied: %02d:%02d sec %7d file(s) %12.6f MByte (%.3f MB/sec).\n"\r
+ "=== tree : %5d dir(s) %7d file(s) %12.6f MByte\n"),\r
+ duration / 60, duration % 60, files, sumSizes / 1E6,\r
+ sumSizes / 1E6 / (duration == 0 ? 1 : duration),\r
+ treeDirs, treeFiles, treeSumSizes / 1E6);\r
+ }\r
}\r
\r
/**\r
}\r
\r
/**\r
- * Gets the arguments for the "statistic" command and execute this.\r
+ * Executes a command.\r
*\r
* @param argc the number of arguments\r
- * @param argav the argument vector\r
+ * @param argv the argument vector\r
+ * @param tool the tool which realizes the command\r
*/\r
-void ReDirTools::list(int argc, const char* argv[]){\r
- ReDirList lister;\r
- lister.list(argc, argv);\r
+void ReDirTools::run(int argc, const char* argv[], ReTool& tool){\r
+ tool.run(argc, argv);\r
}\r
-\r
/**\r
* Gets the arguments for any command and execute this.\r
*\r
argv++;\r
const char* arg0 = argv[0];\r
if (isArg("batch", arg0))\r
- tools.batch(argc, argv);\r
+ ReDirBatch().run(argc, argv);\r
else if (isArg("list", arg0))\r
- tools.list(argc, argv);\r
+ ReDirList().run(argc, argv);\r
else if (isArg("help", arg0))\r
tools.help(argc, argv);\r
else if (isArg("statistic", arg0))\r
- tools.statistic(argc, argv);\r
+ ReDirStatistic().run(argc, argv);\r
else if (isArg("synchronize", arg0))\r
- tools.synchronize(argc, argv);\r
+ ReDirSync().run(argc, argv);\r
+ else if (isArg("touch", arg0))\r
+ ReDirTouch().run(argc, argv);\r
else if (isArg("test", arg0)){\r
void testAll();\r
testAll();\r
return 0;\r
}\r
\r
-/**\r
- * Gets the arguments for the "statistic" command and execute this.\r
- *\r
- * @param argc the number of arguments\r
- * @param argav the argument vector\r
- */\r
-void ReDirTools::statistic(int argc, const char* argv[]){\r
- ReDirStatistic statistic;\r
- statistic.run(argc, argv);\r
-}\r
-\r
-/**\r
- * Gets the arguments for the "synchronize" command and execute this.\r
- *\r
- * @param argc the number of arguments\r
- * @param argav the argument vector\r
- */\r
-void ReDirTools::synchronize(int argc, const char* argv[]){\r
- ReDirSync sync;\r
- sync.synchronize(argc, argv);\r
-}\r
-\r