消解炼金术

02_hugo MD文件收纳方案

小岛建设

hugo对md文件统一管理的常见方案之一是在archetype文件夹内添加模板样式,然后每次通过cmd/powershell的hugo new指令生成对应模版样式。但如此每次都要求输入:

hugo new --kind archetype-01 01file/01text.md

生成的md文件继承archetype中模版的格式。

但我希望实现:将notion中的md文件一键分类入对应文件夹后,不必再使用终端新建,只通过IDE在对应文件夹内新建md文件就可以自动继承父模版,不必在单个博客md文件内生成多余的front matter内容。我的需求是主分类文件夹下包含子文件夹分类,子文件夹有固定tag,避免手动添加或多次键入date和title。

第一步 通过powershell的脚本完成一键分类

特殊要求是显式指定UTF-8编码处理避免生成乱码:

$basePath = ".\content\03archetype"

# 中文标签 -> 英文子文件夹映射
$tagMap = @{
    "book" = "01"
    "movie" = "02"
}

Get-ChildItem $basePath -Filter *.md | ForEach-Object {

    # 只读取前4行并指定编码 UTF8
    $lines = Get-Content $_.FullName -TotalCount 4 -Encoding UTF8
    $bodyLines = Get-Content $_.FullName -Encoding UTF8 | Select-Object -Skip 4

    $title = ""
    $tag = ""
    $date = $null  # 用 null 来表示没有找到日期

    foreach ($line in $lines) {
        if ($line -match '^#\s*(.+)$') {
            $title = $matches[1]
        } elseif ($line -match '^Tags:\s*(.+)$') {
            $tag = $matches[1]
        } elseif ($line -match '^date:\s*(.+)$') {
            try {
                $dateObj = Get-Date $matches[1]
                $date = $dateObj.ToString("yyyy-MM-dd")
            } catch {
                $date = (Get-Date).ToString("yyyy-MM-dd")
            }
        }
    }

    if ($title -eq "") { return }
    # 如果没有在 Front Matter 中找到日期,跳过日期的修改
    if ($date -eq $null) {
        # 如果没有 `date` 字段,则不修改日期,保持原样
        $date = ""  # 可以选择空字符串或其他标识,表示不修改 `date`
    }
    $newHeader = @(
        '---'
        "title: `"$title`""
        "tags: [`"$tag`"]"
        "date: $date"
        "draft: false"
        '---'
        ''
    )

    $newContent = $newHeader + $bodyLines

    # 写回文件时显式 UTF-8 编码
    Set-Content $_.FullName $newContent -Encoding UTF8

    # 根据 Tags 移动文件到英文子文件夹
    if ($tagMap.ContainsKey($tag)) {
        $targetDir = Join-Path $basePath $tagMap[$tag]
        if (!(Test-Path $targetDir)) {
            New-Item -ItemType Directory -Path $targetDir | Out-Null
        }
        Move-Item $_.FullName (Join-Path $targetDir $_.Name)
    }
}

同时可以顺便用脚本将分好类后的多余文本删除/重命名文件标题。

第二步 在每个文件夹下新建_index.md

Hugo的生成逻辑里,文件夹只有在有_index.md的文件时,才可以解析显示页面,不报错。页面md文件的内容是front matter,根据个性化需求填写。例如:

\content\05architect\_index.md
---
title: "Ⅴ测试篇"
navtitle: "测试篇 ▪ 信息留档"
draft: false
---

\content\05architect\05_01\_index.md
---
title: "小岛建设"
cascade:
  tags: ["小岛建设"]
  draft: false
---

其中cascade下的内容就是关键的继承部分,完成这个配置后,新建博文md文件就不必再手动填写tags等内容了,只需要在对应tag文件夹下新建md,键入文本,即可生成博文内容。

第三步 避免重复键入日期与title

因为不愿在md里键入额外的frontmatter,所以每次新建md文件会将时间添加入文件名,一来是键入直接快速,二来也方便排序管理,hugo很贴心地提供了文件名下对应格式的日期识别功能,具体实现只用在配置toml中写入:

[frontmatter]
date = [":filename",":default" ]

新建md时日期格式以"YYYY-MM-DD"格式输入即可识别。

而title部分研究发现toml内不支持动态读取(也可能是我没有调试成功),所以我采用了很呆的方法:为了文件管理便捷性放弃配置title。转而在需求显示标题的layouts中用go template进行文件名节选,实现网页浏览可读性。

     {{ if .Title }}
     {{ .Title }}
     {{ else }}
     {{ $filename := .File.ContentBaseName }}
     {{ $title := replaceRE `^\d{4}-\d{2}-\d{2}_` "" $filename }}
     {{ $title | replaceRE "-" " " | title }}
     {{ end }}

例如本篇博文的文件标题为:<2026-04-14_02_hugo MD文件收纳方案.md>,经过处理后在前端显示为<02_hugo MD文件收纳方案>。

© 2026 消解炼金术 | 
Powered by Hugo and Cloudflare