Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for robomove.cs

(view source code of robomove.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6.  
  7.  
  8. namespace RobvanderWoude
  9. {
  10. 	class RoboMove
  11. 	{
  12. 		static string progver = "1.00";
  13. 		static string logfile = Path.Combine( Directory.GetCurrentDirectory( ), "RoboMove.log" );
  14. 		static List<string> logtext = new List<string>( );
  15. 		static bool debugmode = false;
  16. 		static bool logging = false;
  17. 		static bool overwritelog = false;
  18. 		static bool testmode = false;
  19. 		static bool verbose = false;
  20. 		static int duplicates = 0;
  21. 		static int newfiles = 0;
  22. 		static int movedfiles = 0;
  23. 		static int matchingfiles = 0;
  24.  
  25.  
  26. 		static int Main( string[] args )
  27. 		{
  28. 			#region Parse Command Line
  29.  
  30. 			if ( args.Length < 2 )
  31. 			{
  32. 				return ShowHelp( );
  33. 			}
  34. 			foreach ( string arg in args )
  35. 			{
  36. 				if ( arg == "/?" )
  37. 				{
  38. 					return ShowHelp( );
  39. 				}
  40. 			}
  41. 			if ( args.Length > 2 )
  42. 			{
  43. 				foreach ( string arg in args.Skip<string>( 2 ) )
  44. 				{
  45. 					if ( arg.Length > 1 && arg[0] == '/' )
  46. 					{
  47. 						switch ( arg.ToUpper( ).Substring( 0, 2 ) )
  48. 						{
  49. 							case "/D":
  50. 								if ( debugmode )
  51. 								{
  52. 									return ShowHelp( "Duplicate command line switch /D" );
  53. 								}
  54. 								debugmode = true;
  55. 								break;
  56. 							case "/L":
  57. 								if ( logging )
  58. 								{
  59. 									return ShowHelp( "Duplicate command line switch /L" );
  60. 								}
  61. 								if ( arg.Length > 4 && arg[2] == ':' )
  62. 								{
  63. 									if ( Directory.Exists( Directory.GetParent( arg.Substring( 3 ) ).FullName ) )
  64. 									{
  65. 										logfile = arg.Substring( 3 );
  66. 									}
  67. 									else
  68. 									{
  69. 										return ShowHelp( "Invalid directory for log file: \"{0}\"", Directory.GetParent( arg.Substring( 3 ) ).FullName );
  70. 									}
  71. 								}
  72. 								else
  73. 								{
  74. 									return ShowHelp( "Invalid logfile specified: {0}", arg );
  75. 								}
  76. 								logging = true;
  77. 								break;
  78. 							case "/O":
  79. 								if ( overwritelog )
  80. 								{
  81. 									return ShowHelp( "Duplicate command line switch /O" );
  82. 								}
  83. 								overwritelog = true;
  84. 								break;
  85. 							case "/T":
  86. 								if ( testmode )
  87. 								{
  88. 									return ShowHelp( "Duplicate command line switch /T" );
  89. 								}
  90. 								testmode = true;
  91. 								break;
  92. 							case "/V":
  93. 								if ( verbose )
  94. 								{
  95. 									return ShowHelp( "Duplicate command line switch /V" );
  96. 								}
  97. 								verbose = true;
  98. 								break;
  99. 							default:
  100. 								return ShowHelp( "Invalid command line switch \"{0}\"", args[2] );
  101. 						}
  102. 					}
  103. 					else
  104. 					{
  105. 						return ShowHelp( "Invalid command line argument \"{0}\"", args[2] );
  106. 					}
  107. 				}
  108. 			}
  109.  
  110. 			// Debug Mode implies Logging to file
  111. 			logging = ( logging || debugmode );
  112.  
  113. 			// Overwrite can only be used if Logging is enabled
  114. 			if ( overwritelog && !logging )
  115. 			{
  116. 				return ShowHelp( "/O switch can only be used with /D or /L" );
  117. 			}
  118.  
  119. 			if ( debugmode )
  120. 			{
  121. 				Display( "\nRoboMove {0}, started on {1}, at {2}\n", progver, DateTime.Now.Date.ToShortDateString( ), DateTime.Now.ToShortTimeString( ) );
  122. 				Display( "#arguments:\t{0}", args.Length.ToString( ) );
  123. 				int i = 0;
  124. 				foreach ( string arg in args )
  125. 				{
  126. 					Display( "argument #{0}:\t\"{1}\"", i.ToString( ), arg );
  127. 					i += 1;
  128. 				}
  129. 				Display( "\nSource Root:\t\"{0}\"", args[0] );
  130. 				Display( "Source exists:\t{0}", Directory.Exists( args[0] ).ToString( ) );
  131. 				Display( "Target Root:\t\"{0}\"", args[1] );
  132. 				Display( "Target exists:\t{0}", Directory.Exists( args[1] ).ToString( ) );
  133. 				Display( "Debug Mode:\t{0}", debugmode.ToString( ) );
  134. 				Display( "Log to File:\t{0}", logging.ToString( ) );
  135. 				Display( "Log File:\t\"{0}\"", logfile );
  136. 				Display( "Log exists:\t{0}", File.Exists( logfile ).ToString( ) );
  137. 				Display( "Overwrite Log:\t{0}", overwritelog.ToString( ) );
  138. 				Display( "Test Mode:\t{0}", testmode.ToString( ) );
  139. 				Display( "Verbose:\t{0}\n", verbose.ToString( ) );
  140. 			}
  141.  
  142. 			// Validate paths of source and target directories
  143. 			string sourcerootdir;
  144. 			string targetrootdir;
  145. 			if ( Directory.Exists( args[0] ) )
  146. 			{
  147. 				try
  148. 				{
  149. 					sourcerootdir = Path.GetFullPath( args[0] );
  150. 				}
  151. 				catch ( Exception e )
  152. 				{
  153. 					return ShowHelp( "Invalid source root directory \"{0}\": {1}", args[0], e.Message );
  154. 				}
  155. 			}
  156. 			else
  157. 			{
  158. 				return ShowHelp( "Source directory \"{0}\" not found", args[0] );
  159. 			}
  160. 			if ( Directory.Exists( args[1] ) )
  161. 			{
  162. 				try
  163. 				{
  164. 					targetrootdir = Path.GetFullPath( args[1] );
  165. 				}
  166. 				catch ( Exception e )
  167. 				{
  168. 					return ShowHelp( "Invalid target root directory \"{0}\": {1}", args[0], e.Message );
  169. 				}
  170. 			}
  171. 			else
  172. 			{
  173. 				return ShowHelp( "Target directory \"{0}\" not found", args[1] );
  174. 			}
  175.  
  176. 			#endregion Parse Command Line
  177.  
  178. 			// List directory trees
  179. 			string[] sourcetreeabs = Directory.GetDirectories( sourcerootdir, "*.*", SearchOption.AllDirectories );
  180. 			string[] targettreeabs = Directory.GetDirectories( targetrootdir, "*.*", SearchOption.AllDirectories );
  181. 			List<string> sourcetree = new List<string>( );
  182. 			List<string> targettree = new List<string>( );
  183.  
  184. 			// Remove root folders from paths
  185. 			int srclen = sourcerootdir.Length;
  186. 			foreach ( string dir in sourcetreeabs )
  187. 			{
  188. 				if ( dir.ToLower( ).IndexOf( sourcerootdir.ToLower( ) ) == 0 )
  189. 				{
  190. 					sourcetree.Add( dir.Substring( srclen ) );
  191. 				}
  192. 				else
  193. 				{
  194. 					Display( "ABORTING: error while building source directory tree list" );
  195. 					return 1;
  196. 				}
  197. 			}
  198. 			int tgtlen = targetrootdir.Length;
  199. 			foreach ( string dir in targettreeabs )
  200. 			{
  201. 				if ( dir.ToLower( ).IndexOf( targetrootdir.ToLower( ) ) == 0 )
  202. 				{
  203. 					targettree.Add( dir.Substring( tgtlen ) );
  204. 				}
  205. 				else
  206. 				{
  207. 					Display( "ABORTING: error while building target directory tree list" );
  208. 					return 1;
  209. 				}
  210. 			}
  211.  
  212. 			// Add missing folders to target tree
  213. 			foreach ( string dir in sourcetree )
  214. 			{
  215. 				if ( !targettree.Contains( dir ) )
  216. 				{
  217. 					targettree.Add( dir );
  218. 					string newdir = Path.Combine( targetrootdir, dir.TrimStart( '\\' ) );
  219. 					if ( MKDIR( newdir ) == 1 && ( debugmode || testmode ) )
  220. 					{
  221. 						return 1;
  222. 					}
  223. 				}
  224. 			}
  225.  
  226. 			// List file trees
  227. 			string[] sourcelistabs = Directory.GetFiles( sourcerootdir, "*.*", SearchOption.AllDirectories );
  228. 			string[] targetlistabs = Directory.GetFiles( targetrootdir, "*.*", SearchOption.AllDirectories );
  229. 			List<string> sourcelist = new List<string>( );
  230. 			List<string> targetlist = new List<string>( );
  231.  
  232. 			// List unique file names
  233. 			SortedList<string, bool> sourcefilenames = new SortedList<string, bool>( ); // string filename, bool unique name
  234. 			foreach ( string file in sourcelistabs )
  235. 			{
  236. 				string name = Path.GetFileName( file );
  237. 				if ( sourcefilenames.ContainsKey( name ) )
  238. 				{
  239. 					sourcefilenames[name] = false;
  240. 				}
  241. 				else
  242. 				{
  243. 					sourcefilenames.Add( name, true );
  244. 				}
  245. 			}
  246. 			SortedList<string, bool> targetfilenames = new SortedList<string, bool>( ); // string filename, bool unique name
  247. 			foreach ( string file in targetlistabs )
  248. 			{
  249. 				string name = Path.GetFileName( file );
  250. 				if ( targetfilenames.ContainsKey( name ) )
  251. 				{
  252. 					targetfilenames[name] = false;
  253. 				}
  254. 				else
  255. 				{
  256. 					targetfilenames.Add( name, true );
  257. 				}
  258. 			}
  259.  
  260. 			// Remove root folders from paths
  261. 			foreach ( string file in sourcelistabs )
  262. 			{
  263. 				if ( file.ToLower( ).IndexOf( sourcerootdir.ToLower( ) ) == 0 )
  264. 				{
  265. 					sourcelist.Add( file.Substring( srclen ) );
  266. 				}
  267. 				else
  268. 				{
  269. 					Display( "ABORTING: error while removing root folder from source directory tree list" );
  270. 					return 1;
  271. 				}
  272. 			}
  273. 			foreach ( string file in targetlistabs )
  274. 			{
  275. 				if ( file.ToLower( ).IndexOf( targetrootdir.ToLower( ) ) == 0 )
  276. 				{
  277. 					targetlist.Add( file.Substring( tgtlen ) );
  278. 				}
  279. 				else
  280. 				{
  281. 					Display( "ABORTING: error while removing root folder from target directory tree list" );
  282. 					return 1;
  283. 				}
  284. 			}
  285.  
  286. 			// Compare directory trees
  287. 			foreach ( string file in targetlist )
  288. 			{
  289. 				string name = Path.GetFileName( file );
  290. 				if ( sourcelist.Contains( file ) )
  291. 				{
  292. 					if ( debugmode || verbose )
  293. 					{
  294. 						Display( "OK: locations of file \"{0}\" in source and target trees match", name );
  295. 						matchingfiles += 1;
  296. 					}
  297. 				}
  298. 				else
  299. 				{
  300. 					if ( sourcefilenames.ContainsKey( name ) && targetfilenames.ContainsKey( name ) )
  301. 					{
  302. 						if ( sourcefilenames[name] && targetfilenames[name] )
  303. 						{
  304. 							string currentlocation = Path.Combine( targetrootdir, file.TrimStart( '\\' ) );
  305. 							string sourcelocation = sourcelist.FirstOrDefault( stringToCheck => stringToCheck.Contains( name ) );
  306. 							string movetolocation = Path.Combine( targetrootdir, sourcelocation.TrimStart( '\\' ) );
  307. 							if ( MOVE( currentlocation, movetolocation ) == 1 && ( debugmode || testmode ) )
  308. 							{
  309. 								return 1;
  310. 							}
  311. 						}
  312. 						else
  313. 						{
  314. 							if ( debugmode || testmode || verbose )
  315. 							{
  316. 								Display( "SKIPPED: duplicate file name \"{0}\"", name );
  317. 							}
  318. 							duplicates += 1;
  319. 						}
  320. 					}
  321. 					else
  322. 					{
  323. 						if ( debugmode || testmode || verbose )
  324. 						{
  325. 							Display( "SKIPPED: file \"{0}\" not found in source tree", name );
  326. 						}
  327. 						// New file in target: SKIP
  328. 						newfiles += 1;
  329. 					}
  330. 				}
  331. 			}
  332.  
  333. 			// Cleanup moved folders from target tree
  334. 			targettree.Sort( );
  335. 			targettree.Reverse( ); // Reversed sort guarantees that empty subfolders will be deleted first
  336. 			foreach ( string dir in targettreeabs )
  337. 			{
  338. 				if ( !sourcetree.Contains( dir ) )
  339. 				{
  340. 					if ( Directory.GetFiles( dir, "*.*", SearchOption.TopDirectoryOnly ).Length == 0 )
  341. 					{
  342. 						if ( Directory.GetDirectories( dir, "*.*", SearchOption.AllDirectories ).Length == 0 )
  343. 						{
  344. 							if ( RMDIR( dir ) == 1 )
  345. 							{
  346. 								return 2;
  347. 							}
  348. 						}
  349. 					}
  350. 				}
  351. 			}
  352.  
  353. 			// End of Main program: show results
  354. 			if ( debugmode || verbose )
  355. 			{
  356. 				Display( "{0} file location{1} in source and target tree matched", matchingfiles.ToString( ), ( matchingfiles == 1 ? String.Empty : "s" ) );
  357. 				Display( "{0} file{1} moved", movedfiles.ToString( ), ( movedfiles == 1 ? " was" : "s were" ) );
  358. 				Display( "{0} duplicate file name{1} found", duplicates.ToString( ), ( duplicates == 1 ? " was" : "s were" ) );
  359. 				Display( "{0} file{1} found in the target tree that did not exist in the source tree", newfiles.ToString( ), ( newfiles == 1 ? " was" : "s were" ) );
  360. 				Display( "\nRoboMove {0}, finished on {1}, at {2}\n", progver, DateTime.Now.Date.ToShortDateString( ), DateTime.Now.ToShortTimeString( ) );
  361. 			}
  362. 			if ( duplicates + newfiles == 0 )
  363. 			{
  364. 				return WriteLog( );
  365. 			}
  366. 			else
  367. 			{
  368. 				if ( debugmode || verbose )
  369. 				{
  370. 					int skipped = duplicates + newfiles;
  371. 					Display( "{0} file{1} skipped, use the following command to finish synchronization:", skipped.ToString( ), ( skipped == 1 ? " was" : "s were" ) );
  372. 					Display( "ROBOCOPY /MIR \"{0}\" \"{1}\"", sourcerootdir, targetrootdir );
  373. 				}
  374. 				if ( WriteLog( ) == 1 )
  375. 				{
  376. 					return 1;
  377. 				}
  378. 				else
  379. 				{
  380. 					return 2;
  381. 				}
  382. 			}
  383. 		}
  384.  
  385.  
  386. 		static void Display( string text, params string[] values )
  387. 		{
  388. 			string newtext = String.Format( text, values );
  389. 			if ( verbose )
  390. 			{
  391. 				Console.WriteLine( newtext );
  392. 			}
  393. 			if ( logging )
  394. 			{
  395. 				logtext.Add( newtext );
  396. 			}
  397. 		}
  398.  
  399.  
  400. 		static int MKDIR( string dir )
  401. 		{
  402. 			if ( testmode )
  403. 			{
  404. 				Display( "Creating directory \"{0}\" skipped in Test Mode", dir );
  405. 				return 0;
  406. 			}
  407. 			if ( debugmode || verbose )
  408. 			{
  409. 				Display( "Creating directory \"{0}\"", dir );
  410. 			}
  411. 			try
  412. 			{
  413. 				Directory.CreateDirectory( dir );
  414. 				if ( debugmode || verbose )
  415. 				{
  416. 					Display( "Directory \"{0}\" created successfully", dir );
  417. 				}
  418. 				return 0;
  419. 			}
  420. 			catch ( DirectoryNotFoundException e )
  421. 			{
  422. 				Display( "Directory not found while trying to create directory \"{0}\": {1}", dir, e.Message );
  423. 				return 1;
  424. 			}
  425. 			catch ( IOException e )
  426. 			{
  427. 				Display( "I/O error while trying to create directory \"{0}\": {1}", dir, e.Message );
  428. 				return 1;
  429. 			}
  430. 		}
  431.  
  432.  
  433. 		static int MOVE( string currentlocation, string newlocation )
  434. 		{
  435. 			if ( testmode )
  436. 			{
  437. 				Display( "Moving file \"{0}\" to \"{1}\" skipped in Test Mode", currentlocation, newlocation );
  438. 				return 0;
  439. 			}
  440. 			if ( debugmode || verbose )
  441. 			{
  442. 				Display( "Moving file \"{0}\" to \"{1}\"", currentlocation, newlocation );
  443. 			}
  444. 			try
  445. 			{
  446. 				File.Move( currentlocation, newlocation );
  447. 				movedfiles += 1;
  448. 				return 0;
  449. 			}
  450. 			catch ( DirectoryNotFoundException e )
  451. 			{
  452. 				Console.Error.WriteLine( "Directory not found while trying to move \"{0}\" to \"{1}\": {2}", currentlocation, newlocation, e.Message );
  453. 				return 1;
  454. 			}
  455. 			catch ( IOException e )
  456. 			{
  457. 				Display( "I/O error while trying to move \"{0}\" to \"{1}\": {2}", currentlocation, newlocation, e.Message );
  458. 				return 1;
  459. 			}
  460. 		}
  461.  
  462.  
  463. 		static int RMDIR( string dir )
  464. 		{
  465. 			if ( testmode )
  466. 			{
  467. 				Display( "Removing directory \"{0}\" skipped in Test Mode", dir );
  468. 				return 0;
  469. 			}
  470. 			if ( debugmode || verbose )
  471. 			{
  472. 				Display( "Removing directory \"{0}\"", dir );
  473. 			}
  474. 			try
  475. 			{
  476. 				Directory.Delete( dir );
  477. 				return 0;
  478. 			}
  479. 			catch ( DirectoryNotFoundException e )
  480. 			{
  481. 				Display( "Directory not found while trying to remove \"{0}\": {1}", dir, e.Message );
  482. 				return 1;
  483. 			}
  484. 			catch ( IOException e )
  485. 			{
  486. 				Display( "I/O error while trying to remove directory \"{0}\": {1}", dir, e.Message );
  487. 				return 1;
  488. 			}
  489. 		}
  490.  
  491.  
  492. 		static int ShowHelp( params string[] errmsg )
  493. 		{
  494.  
  495. 			/*
  496. 			RoboMove,  Version 1.00
  497. 			Move files in target directory tree to make it match the source directory tree
  498.  
  499. 			Usage:    ROBOMOVE  sourcedir  targetdir  [ options ]
  500.  
  501. 			Where:    "sourcedir"   is the source tree root directory
  502. 			          "targetdir"   is the target tree root directory
  503. 			Options:  /D            Debugging mode: more screen output than Verbose
  504. 			          /L[:logfile]  enable Logging
  505. 			                        (default logfile: RoboMove.log in current directory)
  506. 			          /O            Overwrite existing logfile (default: append)
  507. 			          /T            Test mode: shows the changes that would be made,
  508. 			                        but doesn't really make any changes
  509. 			          /V            Verbose mode: display every action for every file
  510.  
  511. 			Notes:    ROBOMOVE is a ROBOCOPY like utility, but instead of copying or
  512. 			          deleting files, it only moves them. It is intended to be used when
  513. 			          large numbers of files have been moved and have to be synchronized
  514. 			          with a slow network drive (moving files is faster then copying).
  515. 			          ROBOCOPY may be required afterwards to finish the synchronization.
  516. 			          Duplicate file names within the directory trees will not be moved.
  517. 			          Return code is 0 if all files were moved and no further action is
  518. 			          required (i.e. no duplicate or new files), 1 in case of command line
  519. 			          errors, 2 if duplicate or new files require ROBOCOPY to be run.
  520.  
  521. 			Written by Rob van der Woude
  522. 			http://www.robvanderwoude.com
  523. 			*/
  524.  
  525. 			if ( errmsg.Length > 0 )
  526. 			{
  527. 				List<string> errargs = new List<string>( errmsg );
  528. 				errargs.RemoveAt( 0 );
  529. 				Console.Error.WriteLine( );
  530. 				Console.ForegroundColor = ConsoleColor.Red;
  531. 				Console.Error.Write( "ERROR:\t" );
  532. 				Console.ForegroundColor = ConsoleColor.White;
  533. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  534. 				Console.ResetColor( );
  535. 			}
  536.  
  537. 			Console.Error.WriteLine( );
  538.  
  539. 			Console.Error.WriteLine( "RoboMove,  Version {0}", progver );
  540.  
  541. 			Console.Error.WriteLine( "Move files in target directory tree to make it match the source directory tree" );
  542.  
  543. 			Console.Error.WriteLine( );
  544.  
  545. 			Console.Error.Write( "Usage:    " );
  546. 			Console.ForegroundColor = ConsoleColor.White;
  547. 			Console.Error.WriteLine( "ROBOMOVE  sourcedir  targetdir  [ options ]" );
  548. 			Console.ResetColor( );
  549.  
  550. 			Console.Error.WriteLine( );
  551.  
  552. 			Console.Error.Write( "Where:    " );
  553. 			Console.ForegroundColor = ConsoleColor.White;
  554. 			Console.Error.Write( "\"sourcedir\"" );
  555. 			Console.ResetColor( );
  556. 			Console.Error.WriteLine( "   is the source tree root directory" );
  557.  
  558. 			Console.ForegroundColor = ConsoleColor.White;
  559. 			Console.Error.Write( "          \"targetdir\"" );
  560. 			Console.ResetColor( );
  561. 			Console.Error.WriteLine( "   is the target tree root directory" );
  562.  
  563. 			Console.Error.Write( "Options:  " );
  564. 			Console.ForegroundColor = ConsoleColor.White;
  565. 			Console.Error.Write( "/D            D" );
  566. 			Console.ResetColor( );
  567. 			Console.Error.Write( "ebugging mode: more screen output than " );
  568. 			Console.Error.Write( "Options:  " );
  569. 			Console.Error.Write( "V" );
  570. 			Console.ResetColor( );
  571. 			Console.Error.WriteLine( "erbose" );
  572.  
  573. 			Console.ForegroundColor = ConsoleColor.White;
  574. 			Console.Error.Write( "          /L[:logfile]" );
  575. 			Console.ResetColor( );
  576. 			Console.Error.Write( "  enable " );
  577. 			Console.ForegroundColor = ConsoleColor.White;
  578. 			Console.Error.Write( "L" );
  579. 			Console.ResetColor( );
  580. 			Console.Error.WriteLine( "ogging" );
  581.  
  582. 			Console.Error.WriteLine( "                        (default logfile: RoboMove.log in current directory)" );
  583.  
  584. 			Console.ForegroundColor = ConsoleColor.White;
  585. 			Console.Error.Write( "          /O            O" );
  586. 			Console.ResetColor( );
  587. 			Console.Error.WriteLine( "verwrite existing logfile (default: append)" );
  588.  
  589. 			Console.ForegroundColor = ConsoleColor.White;
  590. 			Console.Error.Write( "          /T            T" );
  591. 			Console.ResetColor( );
  592. 			Console.Error.WriteLine( "est mode: shows the changes that would be made" );
  593.  
  594. 			Console.Error.WriteLine( "                        but doesn't really make any changes" );
  595.  
  596. 			Console.ForegroundColor = ConsoleColor.White;
  597. 			Console.Error.Write( "          /V            V" );
  598. 			Console.ResetColor( );
  599. 			Console.Error.WriteLine( "erbose mode: display every action for every file" );
  600.  
  601. 			Console.Error.WriteLine( );
  602.  
  603. 			Console.Error.WriteLine( "Notes:    ROBOMOVE is a ROBOCOPY like utility, but instead of copying or" );
  604.  
  605. 			Console.Error.WriteLine( "          deleting files, it only moves them. It is intended to be used when" );
  606.  
  607. 			Console.Error.WriteLine( "          large numbers of files have been moved and have to be synchronized" );
  608.  
  609. 			Console.Error.WriteLine( "          with a slow network drive (moving files is faster then copying)." );
  610.  
  611. 			Console.Error.WriteLine( "          ROBOCOPY may be required afterwards to finish the synchronization." );
  612.  
  613. 			Console.Error.WriteLine( "          Duplicate file names within the directory trees will not be moved." );
  614.  
  615. 			Console.Error.WriteLine( "          Return code is 0 if all files were moved and no further action is" );
  616.  
  617. 			Console.Error.WriteLine( "          required (i.e. no duplicate or new files), 1 in case of command line" );
  618.  
  619. 			Console.Error.WriteLine( "          errors, 2 if duplicate or new files require ROBOCOPY to be run." );
  620.  
  621. 			Console.Error.WriteLine( );
  622.  
  623. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  624.  
  625. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  626.  
  627. 			return 1;
  628. 		}
  629.  
  630.  
  631. 		static int WriteLog( )
  632. 		{
  633. 			if ( logging )
  634. 			{
  635. 				try
  636. 				{
  637. 					StreamWriter file = new StreamWriter( logfile, !overwritelog, Encoding.Default );
  638. 					foreach ( string line in logtext )
  639. 					{
  640. 						file.WriteLine( line );
  641. 					}
  642. 					file.Close( );
  643. 				}
  644. 				catch ( Exception e )
  645. 				{
  646. 					return ShowHelp( "Error writing logfile: {0}", e.Message );
  647. 				}
  648. 			}
  649. 			return 0;
  650. 		}
  651. 	}
  652. }
  653.  
  654.  

page last modified: 2024-04-16; loaded in 0.0134 seconds