diff --git a/README.md b/README.md index 6aa15d3..e285bf2 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,11 @@ Extracts and organizes documents from FileCabinet CS (Thomson Reuters) using GUI python fccs_scan.py ``` -Reads the restored FCCS backup directory and writes all drawer IDs (subfolder names) to `drawer_ids.txt`. It also: +Reads the FCCS data directory (`backup_dir`) and writes all drawer IDs (subfolder names) to `drawer_ids.txt`. It also: -- **Flags prefix clashes** — if one drawer ID is a prefix of another (e.g. `02218` and `02218A`), searching the **base** ID in FCCS pops up a selection box that breaks plain automated navigation. These clashes are reported, and the base (shorter) IDs are auto-seeded into `ignore.txt`. The longer, more-specific IDs (`02218A`) search fine and export normally; the base IDs are handled by the separate clash-export script. +- **Skips non-drawer entries** — only subdirectories are treated as drawers. When `backup_dir` points at FCCS's live data directory (the Restore directory), that folder also contains system folders whose names start with `$` and miscellaneous loose files; both are ignored. +- **Normalizes drawer IDs** — FileCabinet CS ignores `.` characters in drawer IDs, so a folder named `A123.TJ` on disk is searched and displayed in the UI as `A123TJ`. The scan strips dots from folder names when writing `drawer_ids.txt` so the ID matches what FCCS expects (searching the dotted form returns no results). This is done at the source because FCCS embeds the same dot-free ID as the prefix of exported filenames, which the reorganize/verify/report tools all key off. If stripping dots collapses two distinct folders onto one ID, the scan logs a **collision warning** rather than silently dropping a drawer. +- **Flags prefix clashes** — if one drawer ID is a prefix of another (e.g. `02218` and `02218A`), searching the **base** ID in FCCS pops up a selection box that breaks plain automated navigation. These clashes are reported, and the base (shorter) IDs are auto-seeded into `ignore.txt`. The longer, more-specific IDs (`02218A`) search fine and export normally. (Clash detection runs on the dot-normalized IDs, since that's what FCCS actually searches.) - **Reports ignored drawers** — any IDs listed in `ignore.txt` that exist in this backup are shown as ones the export will skip. **Ignoring drawers:** The scan creates `ignore.txt` (at `ignore_file`, default `C:\Migration\ignore.txt`) if it doesn't exist and pre-fills it with the clash base IDs — searching those in FCCS shows a selection box that stalls the plain export, so they're skipped by the main export. Open the file and: diff --git a/fccs_scan.py b/fccs_scan.py index d245d38..cf653cb 100644 --- a/fccs_scan.py +++ b/fccs_scan.py @@ -86,11 +86,23 @@ def main(): # (e.g. the Restore directory) there are also system folders that start with # "$" and miscellaneous loose files — skip both. The isdir check drops the # files; the "$" prefix check drops the system folders. - drawer_ids = sorted( + raw_dirs = [ name for name in os.listdir(backup_dir) if not name.startswith("$") and os.path.isdir(os.path.join(backup_dir, name)) - ) + ] + + # FileCabinet CS ignores "." in drawer IDs: a folder named "A123.TJ" on disk + # is searched and displayed in the UI as "A123TJ", so searching the dotted + # form returns nothing. Everything downstream uses the UI form — export types + # the ID into the search box, and FCCS embeds the same dot-free ID as the + # prefix of exported filenames (which manifest names and verify/report keys + # are matched against) — so normalize by stripping dots here at the source. + normalized = {} + for name in raw_dirs: + did = name.replace(".", "") + normalized.setdefault(did, []).append(name) + drawer_ids = sorted(normalized) with open(output_file, "w", encoding="utf-8") as f: for did in drawer_ids: @@ -98,6 +110,17 @@ def main(): log(f"Found {len(drawer_ids)} drawers, written to {output_file}") + # Warn if stripping dots collapsed two distinct folders onto one FCCS ID — + # that would silently drop a drawer from the inventory otherwise. + collisions = {did: names for did, names in normalized.items() if len(names) > 1} + if collisions: + log("-" * 60) + log(f"WARNING: {len(collisions)} drawer ID(s) collide after removing " + "'.' — multiple folders map to a single FCCS ID:") + for did, names in sorted(collisions.items()): + log(f" {did} <- {', '.join(sorted(names))}") + log("-" * 60) + # Flag prefix clashes: FCCS search on the shorter ID pops a selection box. clashes = check_for_clashes(drawer_ids) if clashes: