How to list all files under /content/docs in the correct order

Hello,

Could some one please help to understand how to sort files under /content/docs in the needed order.

I get the list of files like this:

{{ with .Site.GetPage "docs" }}
  {{ template "docs-files" (dict "Section" . "CurrentPage" $) }}
{{ end }}

But the order in which directories are displayed are off, meaning that the sub directory is actually placed above the parent, e.g.:

docs/A/a.md
docs/A/b.md
docs/B/C/a.md
docs/B/C/b.md
docs/B/C/c.md
docs/B/a.md
docs/B/b.md

Needed order:

docs/A/a.md
docs/A/b.md
docs/B/a.md
docs/B/b.md
docs/B/C/a.md
docs/B/C/b.md
docs/B/C/c.md

It would be helpful to see docs-files, whatever that is.

Hello, Joe!

I’m not sure what you mean exactly. I’m very new to Hugo and Go.

Although, I’m not bind to the current code (provided in the example), any would work. I just need to read the files under doc/ in the expected order (provided on the example above).

The ultimate point is to create a menu out of that directory structure, where each directory becomes a section name. It doesn’t seem to be a problem. The only obstacle at the moment is the initial sorting. I managed to sort files by File.Path but that also reverses the file names order.

Thank you for your help!

{{ template "docs-files" ... }}

It’s calling a template you’ve defined as “docs-files”. Maybe should search your code for “docs-files”.

This is the full code that I came up with:

<!-- Get all pages under content/doc/ -->
{{ with .Site.GetPage "docs" }}
  {{ template "docs-files" (dict "Section" . "CurrentPage" $) }}
{{ end }}

<!-- Print docs structure -->
{{ define "docs-files" }}
{{ $categorized := slice }}
  <aside>
    {{ $pages := .Section.Pages }}
    {{ range (sort $pages "File.Path").Reverse }}
      {{ $indent := sub (.Page.RelPermalink | strings.Count "/") 3 }}
      <div class="docs-menu-indent-{{ $indent }}">
        {{ $current := eq $.CurrentPage .Page }}
        {{ $section := replaceRE ".*/(.*)/.*" "$1" .Page.File.Path }}
        {{ if not (in $categorized $section)  }}
          {{ if ne (substr $section 0 (len "docs/")) "docs/" }}
            {{ $categorized = $categorized | append $section }}
            <tt>{{ $section }}</tt><br>
          {{ end }}
        {{ end }}
        <a href="{{ .RelPermalink }}"{{ if $current }} class="active"{{ end }}>
          {{ .LinkTitle }}
        </a>
      </div>
    {{ end }}
  </aside>
{{ end }}

This code produces:

B
  b.md
  a.md
  C
    c.md
    b.md
    a.md
b.md
a.md

My goal is to keep files sorted alphabetically in each section.

With this structure:

content/
├── docs/
│   ├── A/
│   │   ├── a.md
│   │   └── b.md
│   └── B/
│       ├── C/
│       │   ├── a.md
│       │   ├── b.md
│       │   └── c.md
│       ├── a.md
│       └── b.md
└── _index.md

I get this order when I run the code you posted above:

C
/docs/b/c/c/
/docs/b/c/b/
/docs/b/c/a/
B
/docs/b/b/
/docs/b/a/
A
/docs/a/b/
/docs/a/a/

If you want to reverse the order, change this:

{{ range (sort $pages "File.Path").Reverse }}

to this:

{{ range (sort $pages "File.Path" }}

Thanks, Joe. Removing reverse in that case also doesn’t help, because it lists directories in the order that isn’t working for categorizing, i.e.:

docs/A/a.md
docs/A/b.md
docs/B/C/a.md
docs/B/C/b.md
docs/B/C/c.md
docs/B/a.md
docs/B/b.md

… would be categorized to:

A
  a.md
  b.md
B
  C
    a.md
    b.md
    c.md
B
  a.md
  b.md

Let’s back up for a second.

There are two methods to partition content files in directories.

Method 1 - Each directory is a Hugo section

This is the idiomatic way to structure content with Hugo, making it very easy to “walk” the structure, and to access each section separately (e.g., give me a list of pages in directory a/b/c/). In addition to the content files, each directory must have an _index.md file — that’s how Hugo knows it’s a section.

This is the right way to structure your data if you want a section menu.

Example
content/
├── section-a/
│   ├── section-a-1/
│   │   ├── _index.md
│   │   ├── page-a-1-1.md
│   │   └── page-a-1-2.md
│   ├── section-a-2/
│   │   ├── section-a-2-1/
│   │   │   ├── _index.md
│   │   │   ├── page-a-2-1-1.md
│   │   │   └── page-a-2-1-2.md
│   │   ├── section-a-2-2/
│   │   │   ├── _index.md
│   │   │   ├── page-a-2-2-1.md
│   │   │   └── page-a-2-2-2.md
│   │   ├── _index.md
│   │   ├── page-a-2-1.md
│   │   └── page-a-2-2.md
│   ├── _index.md
│   ├── page-a-1.md
│   └── page-a-2.md
├── section-b/
│   ├── section-b-1/
│   │   ├── _index.md
│   │   ├── page-b-1-1.md
│   │   └── page-b-1-2.md
│   ├── section-b-2/
│   │   ├── _index.md
│   │   ├── page-b-2-1.md
│   │   └── page-b-2-2.md
│   ├── _index.md
│   ├── page-b-1.md
│   └── page-b-2.md
└── _index.md


Method 2 - Just a bunch of nested directories

To “walk” the structure, we need to look at the file system. While you can then build links to the content pages, you cannot build links to the directories themselves. And there are other drawbacks.

Example
content/
├── section-a/
│   ├── section-a-1/
│   │   ├── page-a-1-1.md
│   │   └── page-a-1-2.md
│   ├── section-a-2/
│   │   ├── section-a-2-1/
│   │   │   ├── page-a-2-1-1.md
│   │   │   └── page-a-2-1-2.md
│   │   ├── section-a-2-2/
│   │   │   ├── page-a-2-2-1.md
│   │   │   └── page-a-2-2-2.md
│   │   ├── page-a-2-1.md
│   │   └── page-a-2-2.md
│   ├── page-a-1.md
│   └── page-a-2.md
├── section-b/
│   ├── section-b-1/
│   │   ├── page-b-1-1.md
│   │   └── page-b-1-2.md
│   ├── section-b-2/
│   │   ├── page-b-2-1.md
│   │   └── page-b-2-2.md
│   ├── page-b-1.md
│   └── page-b-2.md
└── _index.md


Your examples have all had the “method 2” structure. If you change to “method 1” it will make everything easier.

Please advise.

Thanks, Joe. I eventually came up to the conclusion that using sorting .ByWeight is easier, i.e. like this:

{{ $pages := .Section.Pages }}
{{ range $pageIndex, $page := $pages.ByWeight }}
    ...
{{ end }}