Templater
Templater copied to clipboard
tp.file.move() doesn't create new directory
Plugin information (please complete the following information):
- OS: iPadOS 15.5
- Templater version: 1.12.0
- Obsidian version: Mobile 1.2.2 (56)
- Templater settings: folder location: [00 Meta/04 templates], Timeout: unknown, could not find in settings.
Describe the bug I have a journal note that places daily entries into a folder by month and year. I use this template daily. It uses a templater javascript block to name the file and move it to the correct location. Creating a new directory if it doesn't exist. Instead, it just stopped running. There did not seem to be any error message or warning that this had failed.
The templater javascript block looks like this:
<%*
let titleName = tp.date.now("YYYY-MM-DD") ;
let fileName = "💌 " + titleName
await tp.file.rename(fileName);
await tp.file.move("10 Dated Notes/11 Journal/" + tp.date.now("YYYY/YYYY-MM/") + fileName);
-%>
Expected behavior I expect the file to be created, renamed, and moved to the directory. If the directory does not exist, it should be created. It has worked every day until today - the first day of the month. I had to manually create the folder to get the template to complete.
If the template needs the directory to be created first, then an error message should appear on the screen, and remain visible until it's resolved.
Screenshots
Additional context I believe that this works on my desktop (MacOS) version of Obsidian, as I've been using this same template for several months without an issue.
You can get around this by using some JS to check if folder exists and create it if it doesn't.
like what @AB1908 said, we need to write js to check if folder exists. See #270 #333. The code below worked for me (tested on windows and android. Idk about mac os).
<%*
let titleName = tp.date.now("YYYY-MM-DD") ;
let fileName = "💌 " + titleName;
const dir = "10 Dated Notes/11 Journal/" + tp.date.now("YYYY/YYYY-MM")
const fileDir = dir + "/" + fileName
if (!await this.app.vault.getAbstractFileByPath(dir)) {
// if path doesnt exist, create folders
await this.app.vault.createFolder(dir)
await tp.file.move(fileDir)
} else if (await this.app.vault.getAbstractFileByPath(fileDir + ".md")) {
// if .md file already exists, append time to avoid duplicate error
await tp.file.move(fileDir + " " + tp.date.now("h-mm-ss a"))
} else {
// if .md file doesnt exist
await tp.file.move(fileDir)
}
%>
Demo
![demo](https://i.imgur.com/aRsAg5n.gif)
No mobile demo sry. My mobile doesnt show nested folders that well, and I dont use mobile at all lol
Hope that helps
~welp
@welpdx it seems very useful. Can you help please to replicate this with templaterJS script? It's painful to insert in every template.
@cogscides, What do you mean by "templaterJS script"?
Thanks @welpdx that worked PERFECTLY.
@htmljenn yay!
@welpdx , what if instead of making a new file with time appended at the end, you could open the already existing note and continue where you left off?
Sure, do that with tp.file.find_tfile()
and then app.vault.append()
.
@hypnosu Try this: It will check if file already exists in folder. If it does exist, it will open it up for editing.
<%*
let titleName = tp.date.now("YYYY-MM-DD");
let fileName = "💌 " + titleName;
const dir = "10 Dated Notes/11 Journal/" + tp.date.now("YYYY/YYYY-MM")
const fileDir = dir + "/" + fileName
if (!await this.app.vault.getAbstractFileByPath(dir)) {
// if path doesnt exist, create folders
await this.app.vault.createFolder(dir)
await tp.file.move(fileDir)
} else if (await this.app.vault.getAbstractFileByPath(fileDir + ".md")) {
// if .md file already exists, open file in current active leaf
var file = await this.app.vault.getAbstractFileByPath(fileDir + ".md")
const active_leaf = this.app.workspace.activeLeaf;
if (!active_leaf) {
new Notice("No active leaf", 5000);
} else {await active_leaf.openFile(file, {state: {mode: "source"},});}
} else {
// if .md file doesnt exist
await tp.file.move(fileDir)
}
%>
Demo
![demo](https://i.imgur.com/zMw8bma.gif)
Yeah, it works, thanks! Is there any function that I could call so that the cursor automatically moves at the end of file upon opening?
Can app.vault.append()
a tp.cursor
command I think but I think it could also be done via some workspace/Editor methods. Not knowledgeable enough to know what that would look like though.
I tried with app.vault.append()
but I kept on getting this error
Cannot create property 'saving' on string
I will look into workspace methods. Thanks.
Added two functions to script:
- Added @AB1908's suggestion to append currently viewed file's content to existing file (if file already exists)
- When opening already existing file, the cursor is placed at the end.
<%*
let titleName = tp.date.now("YYYY-MM-DD");
let fileName = "💌 " + titleName;
const dir = "10 Dated Notes/11 Journal/" + tp.date.now("YYYY/YYYY-MM")
const fileDir = dir + "/" + fileName
if (!await this.app.vault.getAbstractFileByPath(dir)) {
// if path doesnt exist, create folders, move and rename current file to new folder
await this.app.vault.createFolder(dir)
await tp.file.move(fileDir)
} else if (await this.app.vault.getAbstractFileByPath(fileDir + ".md")) {
// if .md file already exists
// append content from current file to existing file
var currentFile = this.app.workspace.getActiveFile()
var file = await this.app.vault.getAbstractFileByPath(fileDir + ".md")
await this.app.vault.append(file,"\n" + await this.app.vault.read(currentFile) + "\n")
// open this existing file in pane
const active_leaf = this.app.workspace.activeLeaf;
if (!active_leaf) {
new Notice("No active leaf", 5000);
} else {
await active_leaf.openFile(file, {state: {mode: "source"},});
//after opening file, move cursor to the end
const active_view=this.app.workspace.getActiveViewOfType(tp.obsidian.MarkdownView);
if (active_view === null) {
new Notice("error",5000)
} else {
const editor = active_view.editor;
var lastlinenum = editor.lastLine();
editor.setCursor(lastlinenum);
}
}
} else {
// if fodler exists, but .md file doesnt exist, just move and rename file to target directly
await tp.file.move(fileDir)
}
%>
Demo
![demo](https://i.imgur.com/IWvLT7W.gif)
Beautiful! Thank you so much! Templater 101.
Hey no problem! Yea I learned alot from making these js scripts for different use cases lol
And thanks @AB1908 for basically the pseudo code lol