Skip to content

Instantly share code, notes, and snippets.

@ddrscott
Last active November 15, 2024 15:23

Revisions

  1. ddrscott revised this gist Nov 15, 2024. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion watch_directory.py
    Original file line number Diff line number Diff line change
    @@ -20,6 +20,8 @@ def check_files(directory, max_age_minutes, last_state_file):
    <directory>: The path to the directory containing the files.
    <max_age_minutes>: The maximum age in minutes for a file to be considered as having changes detected.
    [last_state_file]: Optional. The path to the file that stores the last done time (default is '.last_state').
    Returns:
    bool: True if all files are older than the max age and the last done time is updated, otherwise False.
    """
    # List all files in the directory and sort them by modification time
    # print(f"Checking files in directory: {glob.glob(os.path.join(directory, '*.*')) }")
    @@ -48,11 +50,12 @@ def check_files(directory, max_age_minutes, last_state_file):
    if last_done_time is None or (newest_file_time > last_done_time.timestamp()):
    print("all done")
    update_last_state(last_state_file)
    return True
    else:
    print("waiting for next batch...")
    else:
    print(f"changes detected: {all_files_old=}, {file=}, {age_minutes:.2f} minutes old")

    return False

    def read_last_state(last_state_file):
    """
  2. ddrscott created this gist Nov 15, 2024.
    7 changes: 7 additions & 0 deletions LICENSE
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    Copyright (c) <year> <copyright holders>

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    108 changes: 108 additions & 0 deletions watch_directory.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    import os
    import glob
    from textwrap import dedent
    from datetime import datetime, timedelta

    def check_files(directory, max_age_minutes, last_state_file):
    """
    Checks files in the specified directory and determines if changes have occurred within the given age limit.
    Hidden files ignored by default.
    Args:
    directory (str): The path to the directory containing the files.
    max_age_minutes (float): The maximum age in minutes for a file to be considered as having changes detected.
    last_state_file (str): The path to the file that stores the last done time.
    Usage:
    python script.py <directory> <max_age_minutes> [last_state_file]
    <directory>: The path to the directory containing the files.
    <max_age_minutes>: The maximum age in minutes for a file to be considered as having changes detected.
    [last_state_file]: Optional. The path to the file that stores the last done time (default is '.last_state').
    """
    # List all files in the directory and sort them by modification time
    # print(f"Checking files in directory: {glob.glob(os.path.join(directory, '*.*')) }")
    files = [
    (f, os.path.getmtime(f))
    for f in glob.glob(os.path.join(directory, '*.*'))
    if os.path.isfile(f)
    ]
    if not files:
    print("No files found in the specified directory.")
    return

    # Read the last state time if it exists
    last_done_time = read_last_state(last_state_file)
    newest_file_time = max(files, key=lambda x: x[1])[1]
    all_files_old = True
    for file, mod_time in files:
    mod_time_datetime = datetime.fromtimestamp(mod_time)
    age_minutes = (datetime.now() - mod_time_datetime).total_seconds() / 60

    if age_minutes < max_age_minutes:
    all_files_old = False
    break

    if all_files_old:
    if last_done_time is None or (newest_file_time > last_done_time.timestamp()):
    print("all done")
    update_last_state(last_state_file)
    else:
    print("waiting for next batch...")
    else:
    print(f"changes detected: {all_files_old=}, {file=}, {age_minutes:.2f} minutes old")


    def read_last_state(last_state_file):
    """
    Reads the last state time from the specified file.
    Args:
    last_state_file (str): The path to the file that stores the last done time.
    Returns:
    datetime: The last done time if it exists and is valid, otherwise None.
    """
    if os.path.exists(last_state_file):
    try:
    with open(last_state_file, 'r') as f:
    return datetime.fromisoformat(f.read().strip())
    except ValueError:
    pass # Ignore invalid date format
    return None


    def update_last_state(last_state_file):
    """
    Updates the last state time in the specified file to the current time.
    Args:
    last_state_file (str): The path to the file that stores the last done time.
    """
    with open(last_state_file, 'w') as f:
    f.write(datetime.now().isoformat())

    def remove_last_state(last_state_file):
    """
    Removes the specified last state file if it exists.
    Args:
    last_state_file (str): The path to the file that stores the last done time.
    """
    if os.path.exists(last_state_file):
    os.remove(last_state_file)

    # Example usage
    if __name__ == "__main__":
    import sys

    if len(sys.argv) < 3 or len(sys.argv) > 4:
    print(dedent(check_files.__doc__))
    sys.exit(1)

    directory = sys.argv[1]
    max_age_minutes = float(sys.argv[2])
    last_state_file = os.path.join(directory,'.last_state') if len(sys.argv) == 3 else sys.argv[3]

    check_files(directory, max_age_minutes, last_state_file)