例子,python基础教程实例之怎么同步文件夹?
用法很简单,如下:
python syncdir.py source_dir target_dir
将文件夹 source_dir 中的文件同步到文件夹 target_dir 中,同步的过程遵循以下规则:
1、如果文件 f1 在 source_dir 中存在,且不在 target_dir 中,则将 f1 拷到 target_dir 中;
2、如果文件 f1 在 source_dir 与 target_dir 中都存在,但最后修改时间不一样或文件大小不一样,则将 f1 从 source_dir 拷到 target_dir 中,覆盖 target_dir 中的原文件。
规则非常简单,而且是单向的,即只保证同步之后 source_dir 中的文件在 target_dir 中保持一致,但 target_dir 中独有的文件不会反向同步到 source_dir 中。
代码:
复制代码 代码示例:
#!/usr/bin/python
# www.jb200.com
# -*- coding: utf-8 -*-
import os
import sys
import shutil
def errExit(msg):
print "-" * 50
print "ERROR:"
print msg
sys.exit(1)
def main(source_dir, target_dir):
print "synchronize '%s' >> '%s'..." % (source_dir, target_dir)
print "=" * 50
sync_file_count = 0
sync_file_size = 0
for root, dirs, files in os.walk(source_dir):
relative_path = root.replace(source_dir, "")
if len(relative_path) > 0 and relative_path[0] in ("/", ""):
relative_path = relative_path[1:]
dist_path = os.path.join(target_dir, relative_path)
if os.path.isdir(dist_path) == False:
os.makedirs(dist_path)
last_copy_folder = ""
for fn0 in files:
fn = os.path.join(root, fn0)
fn2 = os.path.join(dist_path, fn0)
is_copy = False
if os.path.isfile(fn2) == False:
is_copy = True
else:
statinfo = os.stat(fn)
statinfo2 = os.stat(fn2)
is_copy = (
round(statinfo.st_mtime, 3) != round(statinfo2.st_mtime, 3)
or statinfo.st_size != statinfo2.st_size
)
if is_copy:
if dist_path != last_copy_folder:
print "[ %s ]" % dist_path
last_copy_folder = dist_path
print "copying '%s' ..." % fn0
shutil.copy2(fn, fn2)
sync_file_count += 1
sync_file_size += os.stat(fn).st_size
if sync_file_count > 0:
print "-" * 50
print "%d files synchronized!" % sync_file_count
if sync_file_size > 0:
print "%d bytes." % sync_file_size
print "done!"
if __name__ == "__main__":
if len(sys.argv) != 3:
if "-h" in sys.argv or "--help" in sys.argv:
print __doc__
sys.exit(1)
errExit(u"invalid arguments!")
source_dir, target_dir = sys.argv[1:]
if os.path.isdir(source_dir) == False:
errExit(u"'%s' is not a folder!" % source_dir)
elif os.path.isdir(target_dir) == False:
errExit(u"'%s' is not a folder!" % target_dir)
main(source_dir, target_dir)
代码说明:
目前这个版本只支持本机不同文件夹下的同步,不支持远程网络同步。
几点注意事项:
1、在 Windows 下,os.path.join 的第一个参数如果以“:”结尾,得到的结果可能不是想要的。比如:os.path.join(“D:”, “tmp”),可能会预期得到 “D:tmp” ,但实际得到的是 “D:tmp” ,所以这样的情况下需要使用 os.sep.join(“D:”, “tmp”) 。
2、os.path.join 的第二个参数如果以“/”开头(Windows 下如果以“/”或“”开头),则第一个参数将被忽略。比如 os.path.join(“tmp”, “/test”) 得到的将是 “/test” 。
3、shutil.copy2 可以将文件拷贝到指定地方,它不仅拷贝文件内容,同时还会把文件的创建时间、最后修改时间等信息一起拷过去。
3、用 os.stat(filename).st_mtime 可以取到指定文件的最后修改时间,这个时间是一个浮点小数。用上面的 shutil.copy2 拷贝的文件虽然能保留文件的最后修改时间,但有时由于浮点精度的问题,可能在小数的最后一两位会有误差。因此,一次同步过后,两个相同文件的 st_mtime 有可能会有微小的不一致,所以,脚本中用了四舍五入,只保留文件最后修改时间小数点后的三位(即精确到微秒)。