Ввиду некоторого разгильдяйства, а может, трудно предсказуемого рабочего графика, приходится мне в основном работать мобильно, на ноутбуке. Очевидно, что работаю я не один, и труды свои надо шарить с коллегами, чтобы ребята что-то доделывали, а где-то и их начинания надо брать и мне в доработку. Системы совместной работы банальны - файловые шары, но это и хорошо, поскольку с ним достаточно просто рабоатать. Вот и озадачился я как бы мне синхронизовать свои "ноутбучные" папки с обшими на шарах.
Я пытался использовать штаный механизм Microsoft "Make Available Off-line", но почему-то до добра это не довело, коллеги смеются до сих пор: файлы, которые были доступны мне оффлайново вошли в какое-то состояние, когда их невозможно удалить даже администратору сервера. Разбираться было лень, оставил это, собственно, администратору сервера, а для себя решил, что никогда больше не буду использовать этот механизм.
Задачу свою решил несложной программкой на C#.
Конфиг имеет простой формат:
Через "|" указываются директории для синхронизации, по одной паре на кждой строке.
С # начинается комментарий.
Имеется ряд флажков, -h - покажет по ним кратенькую справку.
Скомпилированная версия с примером конфига и лога доступна здесь.
В целом, если я буду как-то и модифицировать этот скриптик, я буду подкладывать новые версии в Google Docs, тогда как исходник иже - менять не буду, лень. Также пока лениво использовать всякие системы социального кодинга, в том числе и контролирующие версии, - все-таки не так часто я занимаются программонаписательством. Исходник, как и в прежние случаи, привожу для того, может, кому какие фрагменты пригодятся для своих нужд.
Исходник - см. ниже:
Я пытался использовать штаный механизм 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.
#
\\VBOXSVR\Documents\bin|C:\Documents and Settings\vtd\My Documents\bin
# FileSync config file. #
#########################
# Format:
# SourceDirectory|DestinationDirectory
#
# Lines started with '#' - are ignored i.e. comments.
# Spaces before and after are ignored as well.
#
\\VBOXSVR\Documents\bin|C:\Documents and Settings\vtd\My Documents\bin
Через "|" указываются директории для синхронизации, по одной паре на кждой строке.
С # начинается комментарий.
Имеется ряд флажков, -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: private static bool SaveBack = false;
14: private static bool DeleteBack = false;
15: private static Regex BackFile;
16: private static bool OneWay = false;
17:
18: private static string Path1, Path2;
19: private static StreamWriter Log;
20: private static string ConfFileName = "FileSync.conf";
21: private static string LogFileName = "FileSync.log";
22:
23: private static string getLogDate()
24: {
25: return DateTime.Now.ToLocalTime().ToString() + "." + DateTime.Now.Millisecond.ToString();
26: }
27: ////////////////////////////////////////////////////////////////////////////////////////////////////////////
28: private static void 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: static void 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(@"\.~fs\d+$");
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: }
3 comments:
Есть отличная прога - goodsync
Спасибо!
Меня только вот это смутило:
http://www.goodsync.com/ru/how-it-works/free-vs-pro
Здесь же - никаких ограничений :-), причем, если что-то не нравится, можно самому поправить как хочется.
Пользовался когда-то Microsoft Sync Toy, был доволен:
http://www.microsoft.com/en-us/download/details.aspx?id=15155
Post a Comment