From 8159b54d336553c86763193db1947e14b7103ff5 Mon Sep 17 00:00:00 2001 From: Jake Gustafson <7557867+poikilos@users.noreply.github.com> Date: Mon, 21 Jun 2021 13:49:37 -0400 Subject: [PATCH] Complete the delete and hidden options. --- forwardfilesync.py | 98 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/forwardfilesync.py b/forwardfilesync.py index a399068..3134d3f 100644 --- a/forwardfilesync.py +++ b/forwardfilesync.py @@ -1,10 +1,26 @@ #!/usr/bin/env python import os +import sys import shutil +import platform -copy_dot_hidden_enable = False -# TODO: NOT YET IMPEMENTED: delete_if_not_on_src_enable = True +# copy_dot_hidden_enable = False +# 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): result = names[0] @@ -13,24 +29,90 @@ def path_join_all(names): 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 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 if level <= 1: - print("#" + " "*level + "synchronizing with \"" + dst + "\"") + print(CMD_COMMENT + " "*level + "synchronizing with \"{}\"" + "".format(dst)) if not os.path.isdir(dst): os.makedirs(dst) + else: + if do_trim: + trim_branch(src, dst, dot_hidden=dot_hidden) if os.path.isdir(folder_path): for sub_name in os.listdir(folder_path): sub_path = os.path.join(folder_path, sub_name) dst_sub_path = os.path.join(dst, sub_name) allow_copy = True - if not copy_dot_hidden_enable: + if not dot_hidden: allow_copy = not sub_name.startswith(".") if allow_copy and os.path.isdir(sub_path): update_tree(sub_path, dst_sub_path, level+1) if allow_copy and os.path.isfile(sub_path): - shutil.copyfile(sub_path, dst_sub_path) + try: + 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 ") + print("forwardfilesync.py --hidden") + flags[name] = True + else: + print("Error: The syntax is invalid. Expected:") + print("forwardfilesync.py ") + print("forwardfilesync.py --hidden") + exit(1) + src = sys.argv[1] + dst = sys.argv[2] + update_tree(src, dst, dot_hidden=flags["hidden"]) + + +if __name__ == "__main__": + main()