updated scan.py to help us error handle the weird searches and alos build an ignore list
This commit is contained in:
@@ -34,7 +34,12 @@ Extracts and organizes documents from FileCabinet CS (Thomson Reuters) using GUI
|
|||||||
python fccs_scan.py
|
python fccs_scan.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Reads the restored FCCS backup directory and writes all drawer IDs (subfolder names) to `drawer_ids.txt`.
|
Reads the restored FCCS backup directory 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 shorter ID in FCCS pops up a selection box that breaks automated navigation. These are reported so you can export them manually or ignore the shorter ID.
|
||||||
|
- **Reports ignored drawers** — any IDs listed in `ignore.txt` that exist in this backup are shown as ones the export will skip.
|
||||||
|
|
||||||
|
**Ignoring drawers:** To exclude specific drawers from export (e.g. password-protected folders that would stall the automation), add their IDs to the file at `ignore_file` (default `C:\Migration\ignore.txt`), one per line. `drawer_ids.txt` stays a full inventory; the export skips anything in the ignore list. Lines starting with `#` are treated as comments.
|
||||||
|
|
||||||
### Step 2: Export Documents
|
### Step 2: Export Documents
|
||||||
|
|
||||||
@@ -88,6 +93,6 @@ Exported filenames follow the format `{drawer_id}_{client_name}_{folder_name}_{c
|
|||||||
|
|
||||||
All scripts read from `config.ini` (or specify `--config path\to\config.ini`).
|
All scripts read from `config.ini` (or specify `--config path\to\config.ini`).
|
||||||
|
|
||||||
- **`[paths]`** -- backup_dir, export_dir, output_dir, drawer_id_file, completed_file, log_file, screenshot_dir, folder_list
|
- **`[paths]`** -- backup_dir, export_dir, output_dir, drawer_id_file, completed_file, ignore_file, log_file, screenshot_dir, manifest_dir, folder_list
|
||||||
- **`[timeouts]`** -- nav_timeout, dialog_timeout, progress_appear, progress_finish, settle, confirm_timeout
|
- **`[timeouts]`** -- nav_timeout, dialog_timeout, progress_appear, progress_finish, settle, confirm_timeout
|
||||||
- **`[controls]`** -- FCCS window class names and button titles (rarely need changing)
|
- **`[controls]`** -- FCCS window class names and button titles (rarely need changing)
|
||||||
|
|||||||
Binary file not shown.
@@ -5,6 +5,7 @@ export_dir = C:\Migration\Export
|
|||||||
output_dir = C:\Migration\Output
|
output_dir = C:\Migration\Output
|
||||||
drawer_id_file = C:\Migration\drawer_ids.txt
|
drawer_id_file = C:\Migration\drawer_ids.txt
|
||||||
completed_file = C:\Migration\completed.txt
|
completed_file = C:\Migration\completed.txt
|
||||||
|
ignore_file = C:\Migration\ignore.txt
|
||||||
log_file = C:\Migration\run_log.txt
|
log_file = C:\Migration\run_log.txt
|
||||||
screenshot_dir = C:\Migration\screenshots
|
screenshot_dir = C:\Migration\screenshots
|
||||||
manifest_dir = C:\Migration\manifests
|
manifest_dir = C:\Migration\manifests
|
||||||
|
|||||||
@@ -137,3 +137,23 @@ def load_lines(path):
|
|||||||
return []
|
return []
|
||||||
with open(path, "r", encoding="utf-8") as f:
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
return [line.strip() for line in f if line.strip() and not line.strip().startswith("#")]
|
return [line.strip() for line in f if line.strip() and not line.strip().startswith("#")]
|
||||||
|
|
||||||
|
|
||||||
|
def check_for_clashes(drawer_ids):
|
||||||
|
"""Find drawer IDs that are a prefix of another drawer ID.
|
||||||
|
|
||||||
|
FCCS searches by prefix, so searching the shorter ID (e.g. '02218')
|
||||||
|
pops up a selection box when a longer ID exists (e.g. '02218A'),
|
||||||
|
which breaks the automated navigation.
|
||||||
|
|
||||||
|
Returns a list of (short_id, [longer_ids...]) tuples, sorted by short_id.
|
||||||
|
Empty list means no clashes.
|
||||||
|
"""
|
||||||
|
ids = sorted(set(drawer_ids))
|
||||||
|
clashes = []
|
||||||
|
for short in ids:
|
||||||
|
matches = [other for other in ids
|
||||||
|
if other != short and other.startswith(short)]
|
||||||
|
if matches:
|
||||||
|
clashes.append((short, matches))
|
||||||
|
return clashes
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ def main():
|
|||||||
paths = {
|
paths = {
|
||||||
"drawer_id_file": cfg.get("paths", "drawer_id_file"),
|
"drawer_id_file": cfg.get("paths", "drawer_id_file"),
|
||||||
"completed_file": cfg.get("paths", "completed_file"),
|
"completed_file": cfg.get("paths", "completed_file"),
|
||||||
|
"ignore_file": cfg.get("paths", "ignore_file"),
|
||||||
"screenshot_dir": cfg.get("paths", "screenshot_dir"),
|
"screenshot_dir": cfg.get("paths", "screenshot_dir"),
|
||||||
"manifest_dir": cfg.get("paths", "manifest_dir"),
|
"manifest_dir": cfg.get("paths", "manifest_dir"),
|
||||||
}
|
}
|
||||||
@@ -391,10 +392,12 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
completed = load_completed(paths["completed_file"])
|
completed = load_completed(paths["completed_file"])
|
||||||
|
ignored = set(load_lines(paths["ignore_file"]))
|
||||||
|
|
||||||
pending = [d for d in all_ids if d not in completed]
|
pending = [d for d in all_ids if d not in completed and d not in ignored]
|
||||||
log(f"Total drawers in list : {len(all_ids)}")
|
log(f"Total drawers in list : {len(all_ids)}")
|
||||||
log(f"Already completed : {len(completed)}")
|
log(f"Already completed : {len(completed)}")
|
||||||
|
log(f"Ignored (skipped) : {len(ignored & set(all_ids))}")
|
||||||
log(f"Remaining to process : {len(pending)}")
|
log(f"Remaining to process : {len(pending)}")
|
||||||
|
|
||||||
if not pending:
|
if not pending:
|
||||||
|
|||||||
29
fccs_scan.py
29
fccs_scan.py
@@ -8,7 +8,9 @@ Writes the sorted list of drawer IDs to the configured drawer_id_file.
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from fccs_config import parse_args, load_config, make_logger
|
from fccs_config import (
|
||||||
|
parse_args, load_config, make_logger, load_lines, check_for_clashes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -18,6 +20,7 @@ def main():
|
|||||||
|
|
||||||
backup_dir = cfg.get("paths", "backup_dir")
|
backup_dir = cfg.get("paths", "backup_dir")
|
||||||
output_file = cfg.get("paths", "drawer_id_file")
|
output_file = cfg.get("paths", "drawer_id_file")
|
||||||
|
ignore_file = cfg.get("paths", "ignore_file")
|
||||||
|
|
||||||
if not os.path.isdir(backup_dir):
|
if not os.path.isdir(backup_dir):
|
||||||
log(f"ERROR: backup directory not found: {backup_dir}")
|
log(f"ERROR: backup directory not found: {backup_dir}")
|
||||||
@@ -34,6 +37,30 @@ def main():
|
|||||||
|
|
||||||
log(f"Found {len(drawer_ids)} drawers, written to {output_file}")
|
log(f"Found {len(drawer_ids)} drawers, written to {output_file}")
|
||||||
|
|
||||||
|
# Report which drawers are set to be ignored (skipped by the export).
|
||||||
|
ignored = set(load_lines(ignore_file))
|
||||||
|
if ignored:
|
||||||
|
present = sorted(ignored & set(drawer_ids))
|
||||||
|
log(f"Ignore list ({ignore_file}): {len(ignored)} IDs, "
|
||||||
|
f"{len(present)} present in this backup — these will be SKIPPED "
|
||||||
|
f"by fccs_export.py: {', '.join(present) if present else '(none present)'}")
|
||||||
|
|
||||||
|
# Flag prefix clashes: FCCS search on the shorter ID pops a selection box.
|
||||||
|
clashes = check_for_clashes(drawer_ids)
|
||||||
|
if clashes:
|
||||||
|
log("-" * 60)
|
||||||
|
log(f"WARNING: {len(clashes)} potential drawer ID clash(es) found.")
|
||||||
|
log("Searching the shorter ID in FCCS may show a selection box "
|
||||||
|
"instead of navigating directly, which breaks the export.")
|
||||||
|
log("Consider exporting these manually, or add the shorter ID to "
|
||||||
|
f"the ignore list ({ignore_file}).")
|
||||||
|
for short, matches in clashes:
|
||||||
|
flag = " [ignored]" if short in ignored else ""
|
||||||
|
log(f" {short}{flag} -> also matches: {', '.join(matches)}")
|
||||||
|
log("-" * 60)
|
||||||
|
else:
|
||||||
|
log("No drawer ID prefix clashes found.")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user