From 0a1ff91b352f333f2be48f88c6ab565fbc320afe Mon Sep 17 00:00:00 2001 From: q Date: Fri, 10 Oct 2025 10:23:24 +0300 Subject: [PATCH] follow speed with file size --- web/transfer-time | 66 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/web/transfer-time b/web/transfer-time index dc6368d..e84aaa7 100755 --- a/web/transfer-time +++ b/web/transfer-time @@ -4,6 +4,7 @@ import argparse import datetime import os import sys +import time def is_digit(d): @@ -78,9 +79,16 @@ def parse_options(): parser.add_argument( "--time", "-t", help="Time used to transfer Units: s,m,h,d or [dd]:[hh]:[mm]:[ss].[ss]... ", default=None ) + parser.add_argument( + "--follow", + help="File name to read size and keep following change speed. Can use --size to estimate ETA", + default=None, + ) parsed = parser.parse_args() if parsed.rate and parsed.speed: parser.error("Can't use both rate and speed") + if parsed.follow: + return parsed if ( sum((int(parsed.speed is None and parsed.rate is None), int(parsed.time is None), int(parsed.size is None))) @@ -245,7 +253,55 @@ def size_human(size, precision=1): return "%.*f%s" % (defPrecision, size, suffixes[suffixIndex]) -if __name__ == "__main__": +def keep_following(opts, max_size): + + start_size = get_files_size(opts.follow) + if start_size is None: + start_size = 0 + last_size = start_size + start_time = time.time() + last_time = start_time + max_str = "" + clr = "\033[K" + speed_lag = [0, 0, 0] + while True: + try: + time.sleep(1) + curr_size = get_files_size(opts.follow) + if curr_size is None: + curr_size = 0 + curr_time = time.time() + time_elapsed = curr_time - start_time + time_diff = curr_time - last_time + size_diff = curr_size - last_size + speed = size_diff / time_diff + speed_lag.append(speed) + speed_lag.pop(0) + speed_mean = sum(speed_lag) / 3 + if max_size: + time_eta = 0 + if speed > 0: + to_transfer = max_size - curr_size + time_eta = round(to_transfer / speed_mean) + if time_eta > 0: + max_str = f", ETA: {time_human(time_eta)}" + else: + max_str = ", ETA: NA" + print( + f"{clr}Transfer time: {time_human(round(time_elapsed))}, size: {size_human(curr_size)}, speed: {size_human(speed_mean)}/s{max_str}", + end="\r", + ) + last_size = curr_size + last_time = curr_time + except Exception as e: + print(e, end="\r") + raise e + except KeyboardInterrupt: + break + print("") + + +def main(): opts = parse_options() speed, size, time = (None, None, None) @@ -270,6 +326,10 @@ if __name__ == "__main__": "Cannot parse size, and it's not a path either ( ex. 11Gb / file.name ), Size: %s" % (opts.size,) ) + if opts.follow is not None: + keep_following(opts, size) + return + if opts.time is not None: time = parse_time(opts.time.lower()) @@ -279,3 +339,7 @@ if __name__ == "__main__": print(f"Transferred size: {size_human(speed * time)}") if speed is None: print(f"Transfer speed: {size_human(size/time)}/s") + + +if __name__ == "__main__": + main()