Simple note-taking script with POSIX sh
Published: 2023-02-04

Do you know Obsidian and Logseq? If you don't, they are one of the most popular note-taking app on the Internet.

I have tried both of them. By far, they are all pretty nice! Obsidian got such a nice default theme and Logseq is free and open source. The thing I don't like is Electron, these apps use it and it feels very janky on my machine, which makes me feel bored after using it for a while when it comes to their workflow.

And I came up with an idea! What if we just use our text editor for taking notes, for example, Neovim? We just have to come up with a script that could organize our notes just like Obsidian or Logseq. This will make note-taking a simple task to do: open your terminal and just take notes!

So we are going to write our script today. This is for educational purposes only, so don't expect that my final results will fulfill your needs! Use this as a reference for creating your own script.

The idea

Let's think about the file structure for our notes. How should we organize them? Logseq, for example, its notes are somewhat like a journal: it creates a new note for each day. This idea is very good if we are minimizing unnecessary works for the end users. So we are going with it!

For the script to work in long term, we will use years, months, and days to store the notes. Our file structure tree will look like this:

.
├── 2022
│   └── Dec
│       ├── 30.md
│       └── 31.md
└── 2023
    ├── Feb
    │   └── 04.md
    └── Jan
        └── 15.md

Now let's go and write our first line of code!

Coding

Create a file in a directory where it could be executed. Name it. I chose note for mine.

We are writing this script in POSIX sh. So add #! /bin/sh on the top of the file.

Nice! Now we need to get a place where we could use to store the notes (or the root of the tree).

#! /bin/sh

# This is where are we going to keep your notes
path="$XDG_DOCUMENTS_DIR/notes"

Just choose. $XDG_DOCUMENTS_DIR is just my custom environment variable for the directory where I kept my documents. So it will be like $HOME/Documents/notes on your machine.

Next! Simple stuff. Let's store the current year, month and day to their dedicated variables.

# We use dates to organize our notes
year="$(date +'%Y')"
month="$(date +'%b')"
day="$(date +'%d')"

full_path="$path/$year/$month"

Basically we are executing the builtin date command to work with the dates. This is just getting specific information of the current date using date features. You can look at its manpage for more details.

Then we are format all of the variables into a path, like the file structure we came up with above. So now full_path looks like: $HOME/Documents/notes/2023/Feb (again, if you are confused, check out date's manpage', other stuff is just basic shell scripting).

Here comes the control flow: What would happen if you run the script for the first time? Or in the new year and beginning of a month? You have to create a folder to store it, of course.

if ! [ -d "$full_path" ]; then
  echo "Creating a directory for the notes at $full_path"
  mkdir -p "$full_path"
fi

With our full_path variable, we check if the whole path exists or not, we create the whole path with mkdir if not. I don't know if this is a safe approach or not, but by far this is the easiest way to confront all of the problems.

And finally, we open up our note with our favorite text editor:

echo "Opening today's note, $year $month $day"
$EDITOR "$full_path/$day.md"

This is it. Make the script executable, then run it! Check out the output of the script! Take notes!

A preview image

Full code

Improve the script to fit your needs. I may update this blog if there is something more efficient to implement the ideas, or bug fixes, I assume.

#! /bin/sh

# This is where are we going to keep your notes
path="$XDG_DOCUMENTS_DIR/notes"

# We use dates to organize our notes
year="$(date +'%Y')"
month="$(date +'%b')"
day="$(date +'%d')"

full_path="$path/$year/$month"

if ! [ -d "$full_path" ]; then
  echo "Creating a directory for the notes at $full_path"
  mkdir -p "$full_path"
fi

echo "Opening today's note, $year $month $day"
$EDITOR "$full_path/$day.md"