FileSync

FileSync
Ввиду некоторого разгильдяйства, а может, трудно предсказуемого рабочего графика, приходится мне в основном работать мобильно, на ноутбуке. Очевидно, что работаю я не один, и труды свои надо шарить с коллегами, чтобы ребята что-то доделывали, а где-то и их начинания надо брать и мне в доработку. Системы совместной работы банальны - файловые шары, но это и хорошо, поскольку с ним достаточно просто рабоатать. Вот и озадачился я как бы мне синхронизовать свои "ноутбучные" папки с обшими на шарах.

Я пытался использовать штаный механизм Microsoft "Make Available Off-line" , но почему-то до добра это не довело, коллеги смеются до сих пор: файлы, которые были доступны мне оффлайново вошли в какое-то состояние, когда их невозможно удалить даже администратору сервера. Разбираться было лень, оставил это, собственно, администратору сервера, а для себя решил, что никогда больше не буду использовать этот механизм.

Задачу свою решил несложной программкой на C#.

Конфиг имеет простой формат:
#########################
# FileSync config file. #
#########################
# Format:
# SourceDirectory|DestinationDirectory
#
# Lines started with '#' - are ignored i.e. comments.
# Spaces before and after are ignored as well.
#
VBOXSVRDocumentsbin|C:Documents and SettingsvtdMy Documentsbin

Через "|" указываются директории для синхронизации, по одной паре на кждой строке.
С # начинается комментарий.

Имеется ряд флажков, -h - покажет по ним кратенькую справку.

Скомпилированная версия с примером конфига и лога доступна здесь .
В целом, если я буду как-то и модифицировать этот скриптик, я буду подкладывать новые версии в Google Docs, тогда как исходник иже - менять не буду, лень. Также пока лениво использовать всякие системы социального кодинга, в том числе и контролирующие версии, - все-таки не так часто я занимаются программонаписательством. Исходник, как и в прежние случаи, привожу для того, может, кому какие фрагменты пригодятся для своих нужд.

Исходник - см. ниже:

   1:  using System;
   2:  using System.IO;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using System.Text;
   6:  using System.Text.RegularExpressions;
   7:   
   8:   
   9:  namespace FileSync
  10:  {
  11:  class Program
  12:      {
  13:  privatestaticbool SaveBack = false;
  14:  privatestaticbool DeleteBack = false;
  15:  privatestatic Regex BackFile;
  16:  privatestaticbool OneWay = false;
  17:   
  18:  privatestaticstring Path1, Path2;
  19:  privatestatic StreamWriter Log;
  20:  privatestaticstring ConfFileName = "FileSync.conf";
  21:  privatestaticstring LogFileName = "FileSync.log";
  22:   
  23:  privatestaticstring getLogDate()
  24:          {
  25:  return DateTime.Now.ToLocalTime().ToString() + "." + DateTime.Now.Millisecond.ToString();
  26:          }
  27:  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  28:  privatestaticvoid ProcessDirectory(string path)
  29:          {
  30:  string[] fa = Directory.GetFiles(path);
  31:  foreach (string f in fa)
  32:              {
  33:  if(DeleteBack && BackFile.IsMatch(f)){
  34:  try { File.Delete(f); }
  35:  catch (Exception e) { Console.WriteLine("ERROR File.Delete: " + e.ToString()); }
  36:  
  37:                      Log.WriteLine(getLogDate() + " DelBack: " + f);
  38:  continue;
  39:                  }
  40:  if ((File.GetAttributes(f) & FileAttributes.Hidden) == FileAttributes.Hidden) continue;
  41:   
  42:  string f2 = f.Replace(Path1, Path2);
  43:  //Console.WriteLine("ProcessDirectory: file: '" + f + "' <> '"+f2+"'");
  44:  
  45:                  DateTime dt1 = File.GetLastWriteTimeUtc(f);
  46:                  DateTime dt2 = File.GetLastWriteTimeUtc(f2);
  47:  if ( DateTime.Compare(dt1,dt2)>0 )
  48:                  {
  49:  //Console.WriteLine("Date compare " + dt1.ToString() + " > " + dt2.ToString());
  50:  if (File.Exists(f2))
  51:                      {
  52:                          Log.WriteLine(getLogDate() + " CopywRewrite: " + f + " (" + dt1.ToLocalTime().ToString() + ") > "
  53:                          + f2 + " (" + dt2.ToLocalTime().ToString() + ")");
  54:  if (SaveBack)
  55:                          {
  56:  //Console.WriteLine(dt2.ToString() + " == " + dt2.Ticks);
  57:  string f2b = f2 + ".~fs" + dt2.Ticks;
  58:  try { File.Move(f2, f2b); }
  59:  catch (Exception e) { Console.WriteLine("ERROR File.Move: " + e.ToString()); }
  60:                              File.SetAttributes(f2b, FileAttributes.Hidden);
  61:                              Log.WriteLine(getLogDate() + " Backup: " + f2 + " > " + f2b);
  62:                          }
  63:                      }
  64:  else Log.WriteLine(getLogDate() + " Copy: " + f + " > " + f2);
  65:   
  66:  try { File.Copy(f, f2, true); }
  67:  catch (Exception e) { Console.WriteLine("ERROR File.Copy: " + e.ToString()); }
  68:                  }
  69:              }
  70:   
  71:  string[] da = Directory.GetDirectories(path);
  72:  foreach (string d in da)
  73:              {
  74:  string d2 = d.Replace(Path1, Path2);
  75:  if (!Directory.Exists(d2))
  76:                  {
  77:  try { Directory.CreateDirectory(d2); }
  78:  catch (Exception e) { Console.WriteLine("ERROR Directory.CreateDirectory: " + e.ToString()); }
  79:                      Log.WriteLine(getLogDate() + " Create: " + d2);
  80:                  }
  81:                  ProcessDirectory(d);
  82:              }
  83:          }
  84:  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  85:  staticvoid Main(string[] args)
  86:          {
  87:  for (int i = 0; i < args.Length; i++ )
  88:              {
  89:  if (args[i] == "-b") SaveBack = true; 
  90:  if (args[i] == "-o") OneWay = true;
  91:  if (args[i] == "-d")
  92:                  {
  93:                      DeleteBack = true;
  94:                      BackFile = new Regex(@".~fsd+$");
  95:                  }
  96:  if (args[i] == "-h")
  97:                  {
  98:                      Console.WriteLine("FileSync - sycronize directories content. Normal run without parameters.");
  99:                      Console.WriteLine("t" + ConfFileName + " - config file.");
 100:                      Console.WriteLine("t" + LogFileName + " - log file.");
 101:                      Console.WriteLine("t-b - save backup files before rewrite with newer version.");
 102:                      Console.WriteLine("t-d - delete previously saved backup files.");
 103:                      Console.WriteLine("t-o - One way. Copy newer files from SourceDir to DestinationDir, and not from DestinationDir to SourceDir.");
 104:                      Console.WriteLine("t-h - show this help.");
 105:                      Console.WriteLine("Freeware. (c) Sergey V Soldatov, 2012-07-29");
 106:                      Console.WriteLine("Any part of this software can be used as desired.");
 107:  return;
 108:                  }
 109:              }
 110:  /*Console.WriteLine(""+SaveBack + OneWay + DeleteBack);//show options
 111:              return;*/
 112:   
 113:  if(File.Exists(ConfFileName)){
 114:                  FileInfo fil = new FileInfo(LogFileName);
 115:   
 116:  try {
 117:                      Log = fil.AppendText();
 118:                      Log.WriteLine(getLogDate() + " Started: "+String.Join(" ",args));
 119:   
 120:                      StreamReader sr = File.OpenText(ConfFileName);
 121:  string l = "";
 122:                      while( (l = sr.ReadLine()) != null){
 123:                          l = l.Trim();
 124:  if (l.IndexOf('#') == 0) continue; //comment
 125:   
 126:  string[] dirs = l.Split('|'); // '|' - delimeter
 127:  //Console.WriteLine("dir0 = '" + dirs[0] + "'; dir1 = '"+dirs[1]);
 128:  if (!Directory.Exists(dirs[0]))
 129:                          {
 130:                              Console.WriteLine("ERROR: Source Directory " + dirs[0] + " does not exists!");
 131:  continue;
 132:                          }
 133:  if (!Directory.Exists(dirs[1]))
 134:                          {
 135:                              Directory.CreateDirectory(dirs[1]);
 136:                              Log.WriteLine(getLogDate() + " Create: " + dirs[1]);
 137:                          }
 138:  //Console.WriteLine("ProcessDirectory '" + dirs[0] + "'");
 139:                          Log.WriteLine(getLogDate() + " Sync: " + dirs[0] + " > " + dirs[1]);
 140:                          Path1 = dirs[0];
 141:                          Path2 = dirs[1];
 142:                          ProcessDirectory(dirs[0]);
 143:  
 144:  //Console.WriteLine("ProcessDirectory '" + dirs[1] + "'");
 145:  if (!OneWay)
 146:                          {
 147:                              Log.WriteLine(getLogDate() + " Sync: " + dirs[1] + " > " + dirs[0]);
 148:                              Path1 = dirs[1];
 149:                              Path2 = dirs[0];
 150:                              ProcessDirectory(dirs[1]);
 151:                          }
 152:                          Log.WriteLine(getLogDate() + " Finished");
 153:                          Log.Flush();
 154:                          Log.Close();
 155:                      }
 156:                  }
 157:  catch(Exception e){
 158:                      Console.WriteLine("ERROR: "+e.ToString());
 159:                  }
 160:              }
 161:  else {
 162:                  Console.WriteLine("ERROR: No Config found!");
 163:  return;
 164:              }
 165:          }
 166:      }
 167:  }
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.

Комплаенс без боли и занудства? Легко!

25 апреля в 11:00 — SECURITM воркшоп для тех, кто хочет делать соответствие стандартам быстро и с умом. Разберём всё на практике. Покажем, как упростить процессы и сэкономить время.

Реклама.18+. ООО «СЕКЪЮРИТМ», ИНН 7820074059


Сергей Солдатов

REPLY-TO-ALL is a double language blog (English/Russian) run by three information security practitioners. Want to discuss information security problems? This is the place.