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:
- Add the "Type:: " line with the subdirectory if it doesn’t exist.
- 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:
-
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.
- I assumed that you are placing "Type:: " on the first line of every text file.
- Whenever "Type:: " appears on the first line, I assume that it appears by itself and that the the line begins with "Type:: ".
- 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.
- I assumed you did not want to have this script modify any files in the root of your Obsidian vault.
- 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
}
else
{
## 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
}
}
popd
}
Write-Host "Finished running. Press any key to continue..."
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")