1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
#! /usr/bin/env python
"""Merge two RedNotebook directories.
To merge .txt files into a destination RedNotebook journal:
0. Install script requirements: "pip install PyYAML"
1. Click on "Save" within RedNotebook.
2. Do a backup.
3. Quit RedNotebook.
4. Merge in your files (adjust paths):
rednotebook-merge.py --dry-run --dest-dir ~/.rednotebook/data --title "my title" /path/to/*.txt
You will see a log like this:
Updating file /home/sglass/.rednotebook/data/2023-02.txt
- merging day 1
- merging day 2
- added new day 3
- merging day 6
written
Updating file /home/sglass/.rednotebook/data/2023-03.txt
- merging day 1
- added new day 21
written
Adding new file 2023-04.txt
- added new day 2
written
It ends with a summary, e.g. Days already present 17, merged 161, added 71
That means that 17 days already had the corresponding contents, 161 days were
merged in and 71 new days were added.
If that looks OK, then
5. Run that again but without the --dry-run flag.
It should merge in the files. You can see things that were merged in since
each item as an 'Added from <my title>: /path/to/xxx.txt' before the merged text.
"""
import argparse
import os
import sys
import yaml
def doit(argv):
"""Merge a list of files into another RedNotebook directory.
Args:
argv (list of str): Program arguments
"""
parser = argparse.ArgumentParser()
parser.add_argument(
"-d",
"--dest-dir",
type=str,
required=True,
help="RedNotebook data directory to merge into",
)
parser.add_argument(
"-t",
"--title",
type=str,
default="",
help="Title of source files, to use when merging",
)
parser.add_argument("src_files", type=str, nargs="+", help="Files to merge in")
parser.add_argument(
"-n", "--dry-run", action="store_true", help="Don't update destination files"
)
args = parser.parse_args(argv[1:])
present, merged, added = 0, 0, 0
merged = 0
for fname in args.src_files:
header = f"Added from {args.title}: {fname}:\n"
# Load data from the source file.
with open(fname, encoding="utf-8") as inf:
in_data = yaml.safe_load(inf)
base = os.path.basename(fname)
# Figure out what the destination filename will be.
dest_fname = os.path.join(args.dest_dir, base)
# If it exists, read it in, since we'll need to update it...
if os.path.exists(dest_fname):
with open(dest_fname, encoding="utf-8") as inf:
dest_data = yaml.safe_load(inf)
print(f"Updating file {dest_fname}")
# ...but if it doesn't exist, create it
else:
dest_data = {}
print(f"Adding new file {base}")
# Work through day by day, merging in the data.
for day in sorted(in_data.keys()):
text = in_data[day]["text"]
# If the day exists, append this text at the end...
if day in dest_data:
if text in dest_data[day]["text"]:
print(f" - already present in day {day}")
present += 1
else:
print(f" - merging day {day}")
dest_data[day]["text"] += "\n\n" + header + text
merged += 1
# but if the day does not exist, create it
else:
print(f" - added new day {day}")
dest_data[day] = {"text": header + text}
added += 1
# Write out the resulting file, if requested.
if not args.dry_run:
with open(dest_fname, "w", encoding="utf-8") as outf:
yaml.dump(dest_data, outf)
print(" written")
print(f"Days already present {present}, merged {merged}, added {added}")
if args.dry_run:
print("Dry run - no changes")
if __name__ == "__main__":
sys.exit(doit(sys.argv))
|