What is the best way to read files in a directory, if the directory may not exist?

I have a question about Hugo’s readDir function, and would like to see if I can improve upon what I have so far. This is the setup:

In production I hash CSS/JS assets, in development I don’t (and in any case, hashed assets change), so I needed a way to read from my generated CSS/JS directories in the static folder.

The code below generates an error when the directory doesn’t exist. Two occasions where there’s not a directory:

  1. When my build process cleans out the directory for replacing it with new files. [Solved by being more specific with my directory cleaning process]
  2. When, for some reason, I don’t include, for instance, a JS file in the site.

The error clears itself up for #1 and I’ve created the requirement to declare the path in the config to solve #2.

This is the code:

{{$css_path := $.Param "dev.css_path"}}
{{with $css_path}}
  {{range readDir .}}
    <link href='{{replace $css_path "static/" "/"}}/{{.Name}}' rel='stylesheet' type="text/css" />

The end result is that whatever is in the declared directory will be created as a link here, no matter what the name or number of files there. Not bad.

I’m wondering if anyone knows of a better way that doesn’t generate errors and/or doesn’t require declaring the path or another scheme to configure it.

I suggest you do this outside of Hugo, i.e. Gulp/Grunt/WebPack/etc.

A “best practice” for this cannot (currently) be built with Hugo alone, but I encourage you to watch this issue:

Not sure I follow. I’m trying to use the Hugo readDir function. I’m generating the code that it’s reading outside of Hugo.

I edited the OP to hopefully be more clear.

You could improve this by wrapping inside fileExists, but you used the phrase “best practice”, which I would hardly call it.

Using fileExists would not be best practice, or my readDir code?

None. If “best anything”, maybe “best workaround”. But instead of fileExists I would probably just always make sure that the folder exists. If you need to clean it, I would just delete the files.

That’s precisely what my code does. Either I’m not making myself clear or I’m missing something major here. At any rate, I don’t want to take any more of your time. I think I’ll just delete the post.

I think I understand.

I suspect this error goes away if you replace “rm -rf myfolder” with rm myfolder/*.* or similar, which is fundamentally different.

That makes sense. I was thinking it would be a way to do so within Hugo, but I imagine your potentially upcoming functionality wouldn’t delete the entire directory either.

As I said, using the fileExist may help. The upcoming functionality is generating (and potentially caching) files as part of the build process (nothing new here), so the problem isn’t really applicable.

With that, something that may be considered best practice would maybe look something like:

{{ $css := resource "main.scss" | resource.Sass }}
{{ if $prod }}
{{  $css := $css |  resource.Digest | resource.Fingerprint }}
{{ end }}

The above example has a scoping issue with the current Go version, but you get the drift.

I see what you’re saying. So users of the (potential) Hugo asset pipeline would generate the hash/Fingerprint on the files inline, whereas with my non-Hugo pipeline, I have to read the directory, so my solution wouldn’t be necessary for them. Got it.

That’s correct – I have, however, avoided the use of “asset pipeline” as that gives users some “other expectations” (plugins).

1 Like