Fix the dry-run plan for renaming log files

Review the AI's codeEasy12 min

Your task

An AI wrote a Bash loop that adds a date prefix to every log file: for f in $(ls *.log); do mv $f 2024-06-01-$f; done. On production it mangled names with spaces and broke on a file named -rf.log. The new version first prints a dry-run plan, one line per file, that a person checks and a script then runs line by line.

An assistant wrote plan_log_renames(filenames, date_prefix), which builds that plan. It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • filenames: the names of the files in the directory.
  • date_prefix: the prefix to add, such as 2024-06-01.
  • Return the plan: one line per name, in input order.

Rules the tests check:

  • If date_prefix is empty or holds anything other than digits from 0 to 9 and -, return ["error:bad_prefix"] and nothing else.
  • For each name, the first rule that applies gives its line:
    1. The name is empty: error:empty_name.
    2. The name contains / or a newline character (\n): error:unsafe_name. A / makes it a path, and a newline would split the line-based plan.
    3. The name does not end with .log, case included: skip:not_a_log.
    4. The name starts with date_prefix followed by -: skip:already_prefixed.
    5. The target, date_prefix, -, then the name, equals any name in filenames or the target of an earlier line: error:collision.
    6. Otherwise: mv -- 'NAME' 'TARGET', with each name in single quotes. Inside the quotes, every ' is written as '\''.

Examples

plan_log_renames(filenames: list[str], date_prefix: str) -> list[str]
Example 1
Inputplan_log_renames(["app.log", "my server.log", "-rf.log", "notes.txt"], "2024-06-01")
Output["mv -- 'app.log' '2024-06-01-app.log'", "mv -- 'my server.log' '2024-06-01-my server.log'", "mv -- '-rf.log' '2024-06-01--rf.log'", "skip:not_a_log"]
Example 2
Inputplan_log_renames(["it's.log", "*.log"], "2024-06-01")
Output["mv -- 'it'\\''s.log' '2024-06-01-it'\\''s.log'", "mv -- '*.log' '2024-06-01-*.log'"]
Example 3
Inputplan_log_renames(["a.log", "2024-06-01-a.log"], "2024-06-01")
Output["error:collision", "skip:already_prefixed"]