|
@ -1,10 +1,26 @@ |
|
|
#!/usr/bin/env python |
|
|
#!/usr/bin/env python |
|
|
import os |
|
|
import os |
|
|
|
|
|
import sys |
|
|
import shutil |
|
|
import shutil |
|
|
|
|
|
import platform |
|
|
|
|
|
|
|
|
copy_dot_hidden_enable = False |
|
|
# copy_dot_hidden_enable = False |
|
|
# TODO: NOT YET IMPEMENTED: delete_if_not_on_src_enable = True |
|
|
# delete_if_not_on_src_enable = True |
|
|
|
|
|
|
|
|
|
|
|
CMD_RMTREE = "rm -Rf" |
|
|
|
|
|
CMD_RM = "rm -f" |
|
|
|
|
|
CMD_COMMENT = "# " |
|
|
|
|
|
CMD_CP = "cp" |
|
|
|
|
|
|
|
|
|
|
|
if platform.system() == "Windows": |
|
|
|
|
|
CMD_RMTREE = "rd /S /Q" |
|
|
|
|
|
# /S: Delete all files and subdirectories and the directory itself. |
|
|
|
|
|
# /Q: Do not ask on global wildcard. |
|
|
|
|
|
CMD_RM = "del /Q /F" |
|
|
|
|
|
# /Q: Do not confirm on wildcard. |
|
|
|
|
|
# /F: Force deleting read-only files. |
|
|
|
|
|
CMD_COMMENT = "REM " |
|
|
|
|
|
CMD_CP = "COPY" |
|
|
|
|
|
|
|
|
def path_join_all(names): |
|
|
def path_join_all(names): |
|
|
result = names[0] |
|
|
result = names[0] |
|
@ -13,24 +29,90 @@ def path_join_all(names): |
|
|
return result |
|
|
return result |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_tree(src, dst, level=0): |
|
|
def trim_branch(src, dst, dot_hidden=True): |
|
|
""" |
|
|
''' |
|
|
|
|
|
Explore dst non-recursively and delete files |
|
|
|
|
|
and subdirectories recursively that are not present on src. |
|
|
|
|
|
|
|
|
|
|
|
Keyword arguments: |
|
|
|
|
|
dot_hidden -- Operate on files and directories even if they are |
|
|
|
|
|
hidden by starting with '.'. |
|
|
|
|
|
''' |
|
|
|
|
|
for sub_name in os.listdir(dst): |
|
|
|
|
|
src_sub_path = os.path.join(src, sub_name) |
|
|
|
|
|
dst_sub_path = os.path.join(dst, sub_name) |
|
|
|
|
|
if not dot_hidden: |
|
|
|
|
|
if sub_name.startswith("."): |
|
|
|
|
|
continue |
|
|
|
|
|
if not os.path.exists(src_sub_path): |
|
|
|
|
|
if os.path.isfile(dst_sub_path): |
|
|
|
|
|
print("{} \"{}\"...".format(CMD_RM, dst_sub_path)) |
|
|
|
|
|
# os.remove(dst_sub_path) |
|
|
|
|
|
else: |
|
|
|
|
|
print("{} \"{}\"...".format(CMD_RMTREE, dst_sub_path)) |
|
|
|
|
|
# shutil.rmtree(dst_sub_path) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_tree(src, dst, level=0, do_trim=True, dot_hidden=False): |
|
|
|
|
|
''' |
|
|
Creates dst if not present, then copies everything from src to dst |
|
|
Creates dst if not present, then copies everything from src to dst |
|
|
recursively. |
|
|
recursively. |
|
|
""" |
|
|
|
|
|
|
|
|
Keyword arguments: |
|
|
|
|
|
do_trim -- Delete files and directories from dst that are not on |
|
|
|
|
|
src. |
|
|
|
|
|
dot_hidden -- Copy files and directories even if hidden by |
|
|
|
|
|
starting with '.'. |
|
|
|
|
|
''' |
|
|
folder_path = src |
|
|
folder_path = src |
|
|
if level <= 1: |
|
|
if level <= 1: |
|
|
print("#" + " "*level + "synchronizing with \"" + dst + "\"") |
|
|
print(CMD_COMMENT + " "*level + "synchronizing with \"{}\"" |
|
|
|
|
|
"".format(dst)) |
|
|
if not os.path.isdir(dst): |
|
|
if not os.path.isdir(dst): |
|
|
os.makedirs(dst) |
|
|
os.makedirs(dst) |
|
|
|
|
|
else: |
|
|
|
|
|
if do_trim: |
|
|
|
|
|
trim_branch(src, dst, dot_hidden=dot_hidden) |
|
|
if os.path.isdir(folder_path): |
|
|
if os.path.isdir(folder_path): |
|
|
for sub_name in os.listdir(folder_path): |
|
|
for sub_name in os.listdir(folder_path): |
|
|
sub_path = os.path.join(folder_path, sub_name) |
|
|
sub_path = os.path.join(folder_path, sub_name) |
|
|
dst_sub_path = os.path.join(dst, sub_name) |
|
|
dst_sub_path = os.path.join(dst, sub_name) |
|
|
allow_copy = True |
|
|
allow_copy = True |
|
|
if not copy_dot_hidden_enable: |
|
|
if not dot_hidden: |
|
|
allow_copy = not sub_name.startswith(".") |
|
|
allow_copy = not sub_name.startswith(".") |
|
|
if allow_copy and os.path.isdir(sub_path): |
|
|
if allow_copy and os.path.isdir(sub_path): |
|
|
update_tree(sub_path, dst_sub_path, level+1) |
|
|
update_tree(sub_path, dst_sub_path, level+1) |
|
|
if allow_copy and os.path.isfile(sub_path): |
|
|
if allow_copy and os.path.isfile(sub_path): |
|
|
|
|
|
try: |
|
|
shutil.copyfile(sub_path, dst_sub_path) |
|
|
shutil.copyfile(sub_path, dst_sub_path) |
|
|
|
|
|
except PermissionError: |
|
|
|
|
|
print(CMD_COMMENT + "PermissionError:") |
|
|
|
|
|
print(CMD_COMMENT + " {} \"{}\" \"{}\"" |
|
|
|
|
|
"".format(CMD_CP, sub_path, dst_sub_path)) |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main(): |
|
|
|
|
|
flags = {} |
|
|
|
|
|
flags["hidden"] = False |
|
|
|
|
|
if len(sys.argv) == 3: |
|
|
|
|
|
pass |
|
|
|
|
|
elif (len(sys.argv) == 4) and (sys.argv[3][:2] == "--"): |
|
|
|
|
|
name = sys.argv[3][2:] |
|
|
|
|
|
if name not in flags: |
|
|
|
|
|
print("Error: The syntax is invalid. Expected:") |
|
|
|
|
|
print("forwardfilesync.py <source> <destination>") |
|
|
|
|
|
print("forwardfilesync.py <source> <destination> --hidden") |
|
|
|
|
|
flags[name] = True |
|
|
|
|
|
else: |
|
|
|
|
|
print("Error: The syntax is invalid. Expected:") |
|
|
|
|
|
print("forwardfilesync.py <source> <destination>") |
|
|
|
|
|
print("forwardfilesync.py <source> <destination> --hidden") |
|
|
|
|
|
exit(1) |
|
|
|
|
|
src = sys.argv[1] |
|
|
|
|
|
dst = sys.argv[2] |
|
|
|
|
|
update_tree(src, dst, dot_hidden=flags["hidden"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
main() |
|
|