I had thousands of notes with this problem, I had left them untitled and used Evernote's feature of showing the first lines to distinguish them, but when moving them to Joplin I only get the titles, so I need to edit the titles to reflect the first line.
So I asked Bing for help to craft some python code to fix this problem. After some back and forth we came up with a program that reads every .enex file in its directory and for each note if the title is "Untitled Note" and there is a first line of text that can be used as a replacement, then the title is changed to reflect the first line.
Use this to modify your .enex files before importing them into Joplin.
Note: This program overwrites the files so keep a backup of the originals if you want to keep them.
Note: I had one bug caused when a source-url field contained an '=' character, not sure why, but when I edited the enex file to delete this line it worked fine.
Note: Some of this code could theoretically be simpler but then it encountered errors when opening complex data files, something to do with non-unicode characters encountered in the .enex files. This is the simplest version that worked for all of the .enex files that I had.
Here's the code:
# max chars in title
titleLength = 40
import re
import html
import os
import xml.etree.ElementTree as ET
# define a function that takes a string as an argument and strips all html fields
def strip_html_fields(new_title):
# use re.sub to replace any html tags with an empty string
# the pattern is < followed by any characters until >, with the flags re.IGNORECASE and re.DOTALL
# the replacement is an empty string
# the string is new_title
return re.sub("<.*?>", "", new_title, flags=re.IGNORECASE | re.DOTALL)
# Define a function that takes a file name as an argument to process that file
def process_file(file_name):
print("##################")
print(file_name)
# parse input.enex file
tree = ET.parse(file_name)
root = tree.getroot()
# Loop through all the notes in the tree
for note in root.findall("note"):
# Get the title and the content of the note
title = note.find("title").text
content = note.find("content").text
# Check if the title is "Untitled Note"
if title == "Untitled Note":
# Find the first div in the content
start = content.find("<div>")
end = content.find("</div>")
# Extract the text between the div tags
new_title = content[start + 5 : end]
new_title = strip_html_fields(new_title)
new_title = new_title[:titleLength]
new_title = new_title.strip()
if new_title:
# Replace the title with the new title
note.find("title").text = new_title
print(new_title)
note.find("content").text = '<![CDATA[' + content + ']]>'
# write the modified tree to output.enex file
tree.write(file_name)
# open the .enex file in binary mode to convert HTML character codes into text equivalents
with open(file_name, "rb") as f:
# read the file content as bytes
data = f.read()
# decode the bytes using utf-8 encoding
text = data.decode("utf-8")
# unescape the HTML character codes using the html.unescape function
text = html.unescape(text)
# open the .enex file in binary mode to write the output
with open(file_name, "wb") as f:
# encode the text using utf-8 encoding
data = text.encode("utf-8")
# write the data to the file using the file object's write method
f.write(data)
# Get the current directory
current_dir = os.getcwd()
# Loop through all the files in the current directory
for file in os.listdir(current_dir):
# Check if the file has the .enex extension
if file.endswith(".enex"):
# Apply the function to the file name
process_file(file)
To use this just save this code in a text file called RenameNotes.py
Place the text file in a directory with some .enex files you wish to transform.
Then open a terminal in this directory and type:
python RenameNotes.py
The resulting .enex files should be able to be imported into Joplin with the note titles reflecting the first line of the note.
Remember, make a backup!
Good luck!