Insert Title into front matter - powershell script

This will search for *.md files in the folder you give it the filepath to + subfolders.
$content: Read the files content into memory.
$newString: Define newstring to be inserted “— title: filenamewithoutextension —”.
Write-Ouput: simple console text for the user.
$set-content: Define the files new full content as the newstring appended with the original text at the end.

$files = Get-ChildItem -path INSERT YOUR NOTES FILEPATH -filter *.md -recurse -force
foreach ($file in $files)
   	$content = Get-Content $file.FullName
	$newString = "---`rtitle: " + $file.BaseName +"`r ---"
	Write-Output "================================ `r `n inserting" $newString " in" $file.FullName
	Set-Content $file.FullName -value $newString, $content

I just used it on 1200+ files :slight_smile:

but test it out on a backup first :smiley: just to be safe.

Edit: When trying to deploy to netlify i am currently getting errors and failed deployment, trying to work out what in the inserted text is causing this.

Edit2: the newlines after and before each — seemed to cause the deployment to fail. Removing those resulted in successful deployment on netlify. Changed script above.


I’ve been looking for a way to do something similar and I’m wondering if I could modify this script for my needs.

What I want to do is prepend one predefined line to every document in my vault, where the contents of the line would be determined by the folder path. For example, add the line “Type:: #Source” to every document within the following folder paths: “Project-1/Sources”, “Project-2/Sources”, etc.

The thing that may cause complications is that I don’t want to add the newString if it already exists, so that I can periodically run the script to apply the rule to new documents without duplicating the line on existing documents.

Do you reckon this could be done?

That is beyond my skills at present time :slight_smile: the way i do things like this, be it visual basic or powershell is i google for other peoples code and then i basically stitch together stuff until it works hehe :slight_smile: You wouldnt necessarily need to check the folder paths, you could just have 2 separate scripts with the source path hardcoded into them. That way you dont have to deal with “which folder path is this?” if then-> “use newstring2” or “use newstring1”. Thats how i would do it atm. 2) checking for already existing newstring in the file? I would imagine you’d only need to run the script once and then you use a template in your vault to make sure all future notes have this type tag ? Or you could: before running a script, use notepad++ to find the string and replace it with “”. So when the script runs it wont create a duplicate string. Otherwise, it’s time to hit up google “how to check for string in file with powershell” or some such search :slight_smile: Also look up “how to do if then in powershell”. I dont doubt it can be done, i just dont know how.

EDIT: I fixed this so that it now runs in PowerShell v5 (this is the default installed on Windows 10 21H1) and v7. This only works on the first line of the file.

I wrote a simple PowerShell script that does this. This script will look for markdown files in each subdirectory within your vault. This script will either:

  1. Add the "Type:: " line with the subdirectory if it doesn’t exist.
  2. Update the "Type:: " line with the new subdirectory.

For example, a Markdown file in “/Dir1/Sub1” will get this added to the top of the file: “Type:: #Dir1/Sub1”.

Some notes:

  1. Make sure you back up your vault before you run this script. I don’t write PowerShell scripts often, so it’s possible there are subtle bugs in this code.
  2. I assumed that you are placing "Type:: " on the first line of every text file.
  3. Whenever "Type:: " appears on the first line, I assume that it appears by itself and that the the line begins with "Type:: ".
  4. I assumed you want this information to be recognized as a tag in your vault. If you don’t want that, delete the hash-tag in the $TAG variable (i.e. it would be "Type:: " instead of “Type:: #”). Also, if you’re aiming for this to be a tag, make sure you don’t have spaces in your folder names.
  5. I assumed you did not want to have this script modify any files in the root of your Obsidian vault.
  6. Save this as a .ps1 file and run it from the root directory of your Obsidian vault.
$TAG = "Type:: #" # Tag that is being added to each file.
$root = [string]$(pwd) + "\" # String of the Obsidian vault directory.
$LINE_BREAK = "`r`n"

# Get a list of all of the directories, recurisvely.
$folders = (Get-ChildItem "." -Recurse -Directory).FullName

foreach ($folder in $folders) {
	# Remove the root directory from the folder name. For example, if your vault is in "C:\Users\John Smith\Obsidian\", instead of "C:\Users\John Smith\Obsidian\Subfolder1" this becomes "Subfolder1". This also replaces "\" with "/" for hierarchial tags in Obsidian.
	$folderName = ($([string]$folder).Replace($root,"")).Replace("\","/")
	pushd "$folder"
	# Find all of the markdown files within the current directory
	$files = Get-ChildItem "." -Name -Filter "*.md"
	foreach ($file in $files) {
		$text = (Get-Content "$file") # Get the text of the current file
		if ($text.Length -gt 1)	{
			$text = $text.Split($LINE_BREAK)
		$tagLine = $text | Select -Index 0 # Read the line where the $TAG is expected to be (1st line).
		if (($text.length -gt 1) -and ($tagLine.length -lt $TAG.length -or $tagLine.Substring(0,$TAG.length) -eq $TAG)) {
			# This code checks to make sure that the 1st line begins with $TAG.
			# First, this checks to make sure that $text is not empty.
			# Second, this checks to see if the 1st line begins with $TAG. Because the Substring method will fail if the length of the string is shorter than the $TAG itself, the code first checks to make sure the length of the line is at least as long as the $TAG itself.
			$text[0] = "$TAG$folderName"
			Set-Content $file -Value $text
			## In this case, the 1st line of the file does not have $TAG. The file could also be empty.
			$text = "$TAG$folderName" + "$LINE_BREAK" + ($text -join "$LINE_BREAK")
			Set-Content $file -Value $text

Write-Host "Finished running. Press any key to continue..."
1 Like

nice ! :slight_smile: