# Editing Joplin .md files directly does not update app contents

**URL:** <https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638>\
**Category:** Support\
**Created:** [19 August 2021 21:17 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638 "2021-08-19T21:17:35Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![MirDavEsc](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/mirdavesc/32/6974_2.png) [@MirDavEsc](https://discourse.joplinapp.org/u/MirDavEsc)\
**Post date:** [19 August 2021 21:17 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/1 "2021-08-19T21:17:35Z")

</div>

I have recently started using command line in Windows 10 (namely Powershell) as a way to quick look for and replace contents across all of my Joplin notes (e.g. replace the string **TODO** with the string **DONE** in every note).

When I run this command, I can see that PowerShell successfully edits the contents of the file, and can manually check the edits in the Md files in another program (e.g. Notepad), but the Joplin app itself does not refresh, even if I close out the application completely and re-open it. Why does this happen, and how can I properly edit the Md files from command-line (e.g. Powershell)?

---

<div class="post-metadata">

**Author:** ![Daeraxa](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/daeraxa/32/6172_2.png) [@Daeraxa](https://discourse.joplinapp.org/u/Daeraxa)\
**Post date:** [19 August 2021 21:53 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/2 "2021-08-19T21:53:42Z")

</div>

The notes are stored in the sqlite database, not as .md files. Are you editing the files in the sync target? In which case you shouldn't be as you will break the metadata that Joplin requires to maintain the sync. EDIT - jackgruber's answer is better

---

<div class="post-metadata">

**Author:** ![JackGruber](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/jackgruber/32/3231_2.png) [@JackGruber](https://discourse.joplinapp.org/u/JackGruber)\
**Post date:** [20 August 2021 01:19 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/3 "2021-08-20T01:19:35Z")

</div>

@MirDavEsc  
Do not directly edit the files in the sync target! This can lead to a lot of sync errors and inconsistencies.  
Use the data [API](https://joplinapp.org/api/references/rest_api/), which can be used e.g. via [powershell](https://discourse.joplinapp.org/t/powershell-script-to-export-notes/13362/5), [python](https://github.com/JackGruber/Joplin-Tools), ...

---

<div class="post-metadata">

**Author:** ![MirDavEsc](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/mirdavesc/32/6974_2.png) [@MirDavEsc](https://discourse.joplinapp.org/u/MirDavEsc)\
**Post date:** [20 August 2021 10:19 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/4 "2021-08-20T10:19:49Z")

</div>

This is a very useful answer, @JackGruber . I knew of the data API before but the tutorial is not great for someone who has no experience with the REST API or curl. Seeing an actual working script and being able to run it is much more helpful (for me at least) in terms of getting started.

The thing that I am trying to do sounds like a good plugin functionality that someone (me?) can build in the future (working name: Line\_Finder):

1. User provides a string pattern (e.g. **TODO** )

2. Plugin searches all notes for every line that has the tag

3. Plugin creates a new note with the format (| Note\_title | Containing\_line |)  
e.g.  
| | |  
| --- | --- |  
| **Title** | **Note** |  
| Daily standups | **TODO** Revert git repo to prior version |  
| Finances | **TODO** Cancel subscription |  
| Side projects | **TODO** Figure out how curl works |

4. Optional: allow for string pattern replacement in original notes after extracting lines (e.g. **TODO** -\> **DONE** )

---

<div class="post-metadata">

**Author:** ![JackGruber](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/jackgruber/32/3231_2.png) [@JackGruber](https://discourse.joplinapp.org/u/JackGruber)\
**Post date:** [20 August 2021 10:27 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/5 "2021-08-20T10:27:00Z")

</div>

There is already a plugin for this.  
You can the [note-overview](https://github.com/JackGruber/joplin-plugin-note-overview) plugin and search for all todos:

```auto
<!-- note-overview-plugin
search: type:todo
fields: status, todo_due, title
sort: todo_completed ASC
-->

```

or for the word todo

```auto
<!-- note-overview-plugin
search: todo
fields: title, excerpt
alias: title AS Title, excerpt AS Note
sort: todo_completed ASC
-->

```

and many more ...

---

<div class="post-metadata">

**Author:** ![rxliuli](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/rxliuli/32/4083_2.png) [@rxliuli](https://discourse.joplinapp.org/u/rxliuli)\
**Post date:** [21 August 2021 00:58 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/6 "2021-08-21T00:58:47Z")

</div>

I previously wrote a batch tool for searching external attachment resources and replacing them with joplin internal attachment resources, but it did not implement a more general batch replacement function.

[https://joplin-utils.rxliuli.com/joplin-batch-web/#/convertExternalLink](https://joplin-utils.rxliuli.com/joplin-batch-web/#/convertExternalLink)

---

<div class="post-metadata">

**Author:** ![MirDavEsc](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/mirdavesc/32/6974_2.png) [@MirDavEsc](https://discourse.joplinapp.org/u/MirDavEsc)\
**Post date:** [9 September 2021 22:07 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/7 "2021-09-09T22:07:38Z")

</div>

Following up on the response: how does the API work if I want to replace text in a note? For instance, in your PowerShell example, you get the body of a note into a variable $body. I want to then do a command like:

```auto
$new_body = $body -replace "to be replaced", "replacement string"

```

and then write new\_body as the contents of the old body (for instance, replace **TODO** with **DONE**.

I saw in the Joplin API ([joplin/api.md at master · laurent22/joplin · GitHub](https://github.com/laurent22/joplin/blob/master/readme/api.md)) that I need to use PUT, but the instructions are unclear as to how to make a working function call. Seems someone has used [POST with PowerShell before here](https://discourse.joplinapp.org/t/send-screenshot-to-joplin-windows/4918), but not PUT.

Any help or clarifications would be appreciated!

---

<div class="post-metadata">

**Author:** ![JackGruber](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/jackgruber/32/3231_2.png) [@JackGruber](https://discourse.joplinapp.org/u/JackGruber)\
**Post date:** [9 September 2021 23:57 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/8 "2021-09-09T23:57:36Z")

</div>

Quick and dirty, no error handling, no validation, no checks, ...

**Set a new body with powershell**

```auto
$endpoint = "http://localhost:27583"
$token = "xxxxxxxxxxxx"
$noteId = "xxxxxxxxxx"
$newProperties = '{"body": "' + $new_body + '"}'
Invoke-WebRequest ($endpoint + "/notes/" + $noteId + "?token=" + $token) -Method Put -Body $newProperties

```

---

<div class="post-metadata">

**Author:** ![MirDavEsc](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/mirdavesc/32/6974_2.png) [@MirDavEsc](https://discourse.joplinapp.org/u/MirDavEsc)\
**Post date:** [12 September 2021 23:08 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/9 "2021-09-12T23:08:13Z")

</div>

Hi Jack, are you sure the last Invoke-WebRequest works? When I run the equivalent of what you show, I get a 500 code server error.

`$noteBody = $noteContent.body`  
`$newBody = $noteBody -replace "\*\*TODO\*\*", " **DONE**"`  
`$newProperties = '{"body": "' + $newBody + '"}'`  
`Invoke-WebRequest ($joplin_endpoint + "/notes/" + $id + "?token=" + $joplin_token) -Method Put -Body $newProperties`  
This produces the error below:  
Message: [The remote server returned an error: (500) Internal Server Error.]

For reference, the below does work, so I am pretty sure my endpoint, token, and other parameters are set correctly:  
`$webContent = Invoke-WebRequest ($joplin_endpoint + "/notes/" + $id+ "?token=" + $joplin_token + "&fields=id,parent_id,title,body") -Method Get`

---

<div class="post-metadata">

**Author:** ![JackGruber](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/jackgruber/32/3231_2.png) [@JackGruber](https://discourse.joplinapp.org/u/JackGruber)\
**Post date:** [13 September 2021 04:39 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/10 "2021-09-13T04:39:27Z")

</div>

Yes I'm sure.  
I think your json for the request is invalid, maybe it contains quotes ...

---

<div class="post-metadata">

**Author:** ![MirDavEsc](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/mirdavesc/32/6974_2.png) [@MirDavEsc](https://discourse.joplinapp.org/u/MirDavEsc)\
**Post date:** [13 September 2021 11:31 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/11 "2021-09-13T11:31:14Z")

</div>

Confirming that what you wrote was correct. It wasn't quotes, but seems to be about how PowerShell handles the carriage return when applying `ConvertFrom-Json`. It seems to get rid of "\n" and replace it with some other carriage return character that breaks the Json encoding.

The solution is after `ConvertFrom-Json` and doing the manipulation (if it's string manipulation, it can also be done in JSON format directly), back-converting the contents using `ConvertTo-Json` cmdlet before using it in the PUT command. This works better than manually encoding $newProperties as done above.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/1/c/1c948e33314e232a0927789508474d8624f4270b.png) [@system](https://discourse.joplinapp.org/u/system)\
**Post date:** [13 October 2021 11:31 UTC](https://discourse.joplinapp.org/t/editing-joplin-md-files-directly-does-not-update-app-contents/19638/12 "2021-10-13T11:31:19Z")

</div>

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