Create file or append to existing file?

There are various times when I want to take a draft and:

  1. Check if a file with the name [[title]].txt exists in a Dropbox location;

  2. If it doesn’t, create it with [[title]].txt as the file name and [[draft]] plus some metadata (a date stamp, mostly) as the content;

  3. If it does exist, simply append [[body]] to the contents, without first line or the metadata

Is there a series of action steps that can do this? Or am I going to have to figure out enough JavaScript to make it work? (I could do it in Python…)

Thanks!

1 Like

If you want to include the first line in the file content on create but not on append that’s the point where you have an issue.

If you just wanted to use the body each time then it would just be this.

Otherwise a script step in your action like this should suffice.

let dbx = Dropbox.create();
let filePath = "/test/" + draft.processTemplate("[[safe_title]]") + ".txt";
let fileContent = dbx.read(filePath);

if (typeof fileContent == 'undefined')
{
	dbx.write(filePath, draft.content, "overwrite", false);
}
else
{
	dbx.write(filePath, fileContent + draft. processTemplate("[[body]]"), "overwrite", false);
}

Hope that helps.

2 Likes

This is fantastic. Thanks so much! Between your script and the examples in the Drafts scripting documentation, I think I see what’s going on and how to modify things still more.

For example, if I want to man’ipulate the existing content of a file (eg, to insert the new material after the old but before my end-of-file metadata), I would modify filecontent from your script …

One question: I see the Dropbox write function has parameters “overwrite” and “add” — i get what overwrite does. Does “add” work like Drafts’ append mode, by adding to an existing file if there is one, or does it add (create) a new/second file if it successfully finds an existing one?

Thanks again!

Here’s how it works with an original file followed by a subsequent file.

  • Add & autorename enabled => two files produced with auto naming of the second file.
  • Add & autorename disabled => first file persists, no overwrite no additional file.
  • Overwrite & autorename enabled => second file overwrites the first.
  • Overwrite & autorename disabled => second file (again) overwrites the first.

Of course, when in doubt, try it out…

let dbx = Dropbox.create();
let filePath = "/test/";
let fileContent = "foo";
let fileExtension= ".txt"

dbx.write(filePath + "Test-A" + fileExtension, fileContent, "add", true);
dbx.write(filePath + "Test-B" + fileExtension, fileContent, "add", false);
dbx.write(filePath + "Test-C" + fileExtension, fileContent, "overwrite", true);
dbx.write(filePath + "Test-D" + fileExtension, fileContent, "overwrite", false);
alert("Let's have a definite pause...");

fileContent = "bar";
dbx.write(filePath + "Test-A" + fileExtension, fileContent, "add", true);
dbx.write(filePath + "Test-B" + fileExtension, fileContent, "add", false);
dbx.write(filePath + "Test-C" + fileExtension, fileContent, "overwrite", true);
dbx.write(filePath + "Test-D" + fileExtension, fileContent, "overwrite", false);
alert("All done. Check your files.");

Make sense?

2 Likes

Perfect. Thanks! Yes, I was plannning to try it out, but I always get twitchy testing out file actions, because of the risk of things going wrong. Also, without an iPad, I’m trying to do all of this on a little phone screen… off to experiment.

Can this script be modified to work with iCloud? I have what sounds like similar wishes to @tf2 only in iCloud (within Drafts area in iCloud).

It should just be a case of switching from Dropbox to FileManager.

Thank you. I was looking at FileManager but was unsure whether that is where I should go. I explore further.

Well I must have tried something different as I am only just now revisiting this. I wish to do the same as @tf2 posted at the start of this thread.

I am a relatively new to scripting. I have been looking at FileManager to see if I can create something similar to @sylumer’s first Dropbox script in this thread. I am getting there, however FileManager does not appear to have an append to file feature that I can find. How can I use FileManager, or can I use FileManager to append to a file?

Thank you!

  1. Read the file content into a variable.
  2. Append the content to the variable.
  3. Overwrite the file with the content of the variable.
1 Like

Ah, thank you. I’ll try that later and report back.

So I have tried, through reading the script references and the scripts in this thread to create a script using Bookmarks and FileManager. This is my first attempt at writing javascript. The problem is that the code below is creating an incorrect file name.

I suspect that it is the let filePath line that it is incorrect as I have changed it a few times and get a different filename, all of which are in the correctly Bookmarked folder.

So for example for this month I would expect a file name 2024-09 Monthly Journal.md, but what I am getting is [object ActionKit.ScriptObjectFileManager]2024-09 Monthly Journal.md.

I have defined three templates before calling the script, FileName, NewFile, and NewEntry.

I’m having fun but have hit a wall. Any advice pointing me in the right direction would be much appreciated.

Thank you.

// Drafts FileManager Script
// Create new journal or append to existing journal

// find or create a named Bookmark
let bookmark = Bookmark.findOrCreate("iAjournal");
let flm = FileManager.createForBookmark(bookmark);

let filePath = flm + draft.processTemplate("[[FileName]]") + ".md";

if (flm.exists(filePath) == 'false')
{
	flm.writeString(filePath, [[NewFile]]);
}
else
{
	let jtd = flm.readString(filePath);
	let newContent = jtd + draft.processTemplate("[[NewEntry]]")
	flm.writeString(filePath, newContent);
}

The FileManager you create in the flm variable is an object and you try to add that object to the file name to create the filePath - which, in Javascript, results in it coercing it to a string representation - thus the garbage.

The path you need for calls to the FileManager are relative to the root of the bookmark. So, if you are just trying to read/write from a file “Test.md” in the root of the folder you associated with your bookmark, you would do something like:

let s = flm.readString("Test.md")
flm.writeString("Test.md", "My String")

So, in your script, chage the line that creates the filePath to:

let filePath = draft.processTemplate("[[FileName]]") + ".md"

You’ve got a few other things going on I see on a quick pass though, I didn’t test this, but cleaned up those here…

// find or create a named Bookmark
let bookmark = Bookmark.findOrCreate("iAjournal");
let flm = FileManager.createForBookmark(bookmark);

let filePath = draft.processTemplate("[[FileName]]") + ".md"

if (!flm.exists(filePath))
{
	flm.writeString(filePath, draft.processTemplate("[[NewFile]]"))
}
else
{
	let jtd = flm.readString(filePath)
	let newContent = jtd + draft.processTemplate("[[NewEntry]]")
	flm.writeString(filePath, newContent)
}

Thank you for explaining my mistake and tidying up the code. Very helpful. I shall try it later and report back.

Many, many thanks. My journal action is now working just I wanted it to. This has been a helpful exercise for me. I’m understanding a little better how JavaScript works and might be tempted to try some more involved actions than I might otherwise have done so in the past.

2 Likes