Skip to content

Instantly share code, notes, and snippets.

@wecsam
Last active May 14, 2024 19:41
Show Gist options
  • Select an option

  • Save wecsam/74aeb122cd3deea3d45ab7c5fad38995 to your computer and use it in GitHub Desktop.

Select an option

Save wecsam/74aeb122cd3deea3d45ab7c5fad38995 to your computer and use it in GitHub Desktop.

Revisions

  1. wecsam revised this gist May 14, 2024. No changes.
  2. wecsam revised this gist Mar 24, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion slowly_feed_onedrive.py
    Original file line number Diff line number Diff line change
    @@ -47,7 +47,7 @@ def move_one_file(src, dst, minimum_free):

    def move_tree(src, dst, minimum_free):
    for dirpath, dirnames, filenames in os.walk(src):
    dst_subdir = os.path.normpath(os.path.join(dst, os.path.relpath(src, dirpath)))
    dst_subdir = os.path.normpath(os.path.join(dst, os.path.relpath(dirpath, src)))
    os.makedirs(dst_subdir, exist_ok=True)
    for filename in filenames:
    move_one_file(os.path.join(dirpath, filename), dst_subdir, minimum_free)
  3. wecsam created this gist May 9, 2021.
    87 changes: 87 additions & 0 deletions slowly_feed_onedrive.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,87 @@
    #!/usr/bin/env python3
    import argparse
    import datetime
    import humanfriendly # pip install humanfriendly
    import os
    import shutil
    import subprocess
    import sys
    import time

    def print_with_time(*args, **kwargs):
    print(datetime.datetime.now(), "-", *args, **kwargs)

    def size(s):
    try: return humanfriendly.parse_size(s)
    except humanfriendly.InvalidSize: raise ValueError

    def wait_for_free_space(dst, minimum_free):
    while True:
    if (free := shutil.disk_usage(dst).free) >= minimum_free: # PEP 572 requires Python 3.8 or later.
    break
    print_with_time(
    "Waiting for free space (available: {}, required: {})...".format(
    humanfriendly.format_size(free, binary=True),
    humanfriendly.format_size(minimum_free, binary=True)
    )
    )
    # Wait 5 minutes, but try to land on the top of the minute.
    time.sleep(300.0 - time.time() % 60.0)

    def move_one_file(src, dst, minimum_free):
    wait_for_free_space(dst, minimum_free)

    print_with_time(src, "->", end=" ")
    sys.stdout.flush()

    try:
    dst = shutil.move(src, dst)
    except (OSError, shutil.Error) as e:
    print("error:", e)
    return
    else:
    print(dst)

    # Free the space up after uploading to OneDrive.
    subprocess.run([r"C:\Windows\System32\attrib.exe", "-P", "+U", dst])

    def move_tree(src, dst, minimum_free):
    for dirpath, dirnames, filenames in os.walk(src):
    dst_subdir = os.path.normpath(os.path.join(dst, os.path.relpath(src, dirpath)))
    os.makedirs(dst_subdir, exist_ok=True)
    for filename in filenames:
    move_one_file(os.path.join(dirpath, filename), dst_subdir, minimum_free)

    def main():
    parser = argparse.ArgumentParser(
    description=
    "This tool moves a file or recursively moves a directory of files. "
    "Before moving each file, it waits for the destination disk to have the specified amount of free space. "
    "After moving each file, it sets its attributes so that OneDrive Files on Demand will free its space up."
    )
    parser.add_argument("src", help="the file to move or the directory from which to move files")
    parser.add_argument("dst", help="the directory to which to move files")
    parser.add_argument(
    "-f", "--free",
    type=size,
    default="8 GiB",
    metavar="size",
    dest="minimum_free",
    help="the amount of space to leave free on the destination disk (default: %(default)s)"
    )

    args = parser.parse_args()
    if os.path.isdir(args.src):
    if not os.path.isdir(args.dst):
    parser.error("If the source is a directory, the destination must be a directory.")
    move = move_tree
    else:
    move = move_one_file

    try:
    move(**vars(args))
    except KeyboardInterrupt:
    print_with_time("^C", file=sys.stderr)

    if __name__ == "__main__":
    main()