How to stop automatic creation of an md file

I have playing with Dataview JS to create an MD file date stamped. See code below:

var MyDate = new Date();
var MyDateString;

MyDate.setDate(MyDate.getDate());

MyDateString = MyDate.getFullYear() 
	+ ('0' + (MyDate.getMonth()+1)).slice(-2) 
	+ ('0' + MyDate.getDate()).slice(-2)  
	+ MyDate.getHours() 
	+ MyDate.getMinutes()
	+ MyDate.getSeconds();

let noteFile = MyDateString + ".md"
let content = MyDateString
const file = await app.vault.create(noteFile, content);

The problem I am facing is that the automatic creation of the file does not stop; it continues almost every second.

Is there a better way to do this?

Well, the dataviewjs is executed at least once when you switch to reading and/or live preview, or when you re-open the note containing the script. If you got it open in multiple windows the script is also executed in either of those if you’re viewing them, and the note changes. This could/should lead to the creation of multiple files with your current setup.

What you want to do is to make sure that this part of your script is executed exactly once, and not more than once. To achieve something like that you need to enter some sort of flag, and check if that flag before creating the file. One option to have such a flag could be to insert the file name into a property of the current note, and check that property before you try to create the file.

The downside of that method is that changing the file you’re currently in, could cause race condition if you are doing other edits in the file, and you very quickly enter into a asynchronous time conundrum.


So how would I approach this task? I would either create a command using either Templater or QuickAdd to create the file for me, and then trigger that command one time most likely using a hotkey. This depends on your use case though.

Is there any particular reason you’re using that way to create your date string instead of using some variant of date formatting? I’ve used an alternate method in the code below. (And I would strongly consider using a proper ISO 8601 date instead of just numbers… Like doing YYYY-MM-DD[T]HH:mm:ss )

Going with the approach above of flagging in the current note’s properties, the following seems to work in my simple testing:

```dataviewjs
const tp = app.plugins.plugins['templater-obsidian'].templater.current_functions_object;
const myDateString = moment().format("YYYYMMDDHHmmss")
const tFile = await tp.file.find_tfile(dv.current().file.path);
console.log(tFile)
console.log(dv.current())
await app.fileManager.processFrontMatter(tFile, fm => {
  if ("file_created" in fm ) {
    console.log("File already created")
  } else {
    fm["file_created"] = myDateString
    console.log(fm)
    console.log("Yay... Creating file: " + myDateString)
  }
})
  
```

This code triggers the creating file code block just once, even if the script is run a multitude of times. Of course, you’d need to exchange my console.log() statements with the actual creation of the files.

A slightly simpler variant of that script, without the dependency on the Templater plugin to get the TFile needed for app.workspace.processFrontMatter() would be:

```dataviewjs
const myDateString = moment().format("YYYY-MM-DD[T]HH:mm:ss")

await app.fileManager.processFrontMatter(app.workspace.getActiveFile(), fm => {
  if ("file_created" in fm ) {
    console.log("File already created")
  } else {
    fm["file_created"] = myDateString
    console.log(fm)
    console.log("Yay... Creating file: " + myDateString)
  }
})
```

Thanks a lot. Got it. There must a flag.
What I don’t see is where the .md file is created. The script writes something in the frontmatter but doesn’t create any file.

By the way, the way I choose to generate the date is just plain javascript. I wanted to see the name of the .md file changing and also its content.

No, my script doesn’t create the file it just add debug output at the places where you need to replace with your existing code to create the files. Just as I mentioned at the bottom of my first reply.

Maybe I am not getting the idea. I added the line that creates the MD file. The flag is there so it should stop, right?

const myDateString = moment().format("YYYYMMDDHHmmss")
const noteFile = myDateString + ".md";
const content =  "text: " + myDateString;

await app.fileManager.processFrontMatter(app.workspace.getActiveFile(), fm => {
  if ("file_created" in fm ) {
	const file = app.vault.create(noteFile, content);
    console.log(`File ${noteFile} already created`)
    
  } else {
    fm["file_created"] = myDateString
    console.log(fm)
    console.log("Yay... Creating file: " + myDateString)
  }
})

Try this:

const myDateString = moment().format("YYYYMMDDHHmmss")
const noteFile = myDateString + ".md";
const content =  "text: " + myDateString;

await app.fileManager.processFrontMatter(app.workspace.getActiveFile(), fm => {
  if ("file_created" in fm ) {
    console.log(`File ${noteFile} already created`)
    
  } else {
    fm["file_created"] = myDateString
    await app.vault.create(noteFile, content);
  }
})

You might need to change fm => { into async (fm) => { if the version above complains asynchronisity issues. But try it as it stands first.

Thank you so much @holroy.

Your script works wonderfully now, both ways: with and without async. There are the two variants:

// holroy: [How to stop automatic creation of a file - Help - Obsidian Forum](https://forum.obsidian.md/t/how-to-stop-automatic-creation-of-a-file/74952/8?u=msfz751)
// write to md file once with flag no-async

const myDateString = moment().format("YYYYMMDDHHmmss")
const noteFile = myDateString + "-no_async.md";
const content =  "text: " + myDateString;

await app.fileManager.processFrontMatter(app.workspace.getActiveFile(), fm => {
  if ("file_created" in fm ) {
	  new Notice(`File ${noteFile} already exists`)
	  console.log(`File ${noteFile} already exists`)
    
  } else {
    fm["file_created"] = myDateString
    app.vault.create(noteFile, content);
    new Notice(`File ${noteFile} just created`)
    console.log(`File ${noteFile} just created`)
  }
})

and the other one:

// holroy: [How to stop automatic creation of a file - Help - Obsidian Forum](https://forum.obsidian.md/t/how-to-stop-automatic-creation-of-a-file/74952/8?u=msfz751)
// write to md file once with flag async

const myDateString = moment().format("YYYYMMDDHHmmss")
const noteFile = myDateString + "-async.md";
const content =  "text: " + myDateString;

await app.fileManager.processFrontMatter(app.workspace.getActiveFile(), async(fm) => {
  if ("file_created" in fm ) {
  	  new Notice(`File ${noteFile} already exists`)
	  console.log(`File ${noteFile} already exists`)
    
  } else {
    fm["file_created"] = myDateString
    await app.vault.create(noteFile, content);
    new Notice(`File ${noteFile} just created`)
    console.log(`File ${noteFile} just created`)
  }
})

To make it write the md file again, the file_created property has to be manually removed. I was thinking on adding a button to remove the property.

Since create returns a promise, you should use await in front of it. If not it might not work as expected.

Your request was for a single creation, so yes you need to remove the property before a new file is created. You could remove it through various other means as well, or if you use a button you could set its value to something allowing for the file to be created again. (Which would require some slight modifications to the script to not only check whether it’s there or not, but also check its value).

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.