Bash Script to convert Hugo Content Files to Page Bundles

Here is a bash script to quickly convert your Content Files to Page Bundles (introduced today with Hugo 0.32)

The following script will convert every markdown into a folder that contains an like so:

for FILE in *.md
  # remove the last dot and subsequent chars to name the folder from the .md
  mkdir -p "$DIR"
  mv "$FILE" "$DIR"
find ./ -iname '*.md' -execdir mv -i '{}' \;

Save the above script into something like make it executable and simply run with


Happy New Year everybody! :boom:


I tried this. didn’t work for me. Can you assist me?

This script is for Linux. If you are on Windows I can’t help. If you’re on MacOs I think that iname is not available and you need a workaround. But I can’t help with that either I’m afraid.

Maybe someone who uses a Mac or Windows could chime in and help.

I use Linux. Ubuntu to be precise. maybe i;m doing something wrong

1 Like

It works on mac fine, thanks @onedrawingperday

However, FYI, it does not handle a section folder like content/post/ That just gets converted to content/post/ Not quite sure how to fix it.

1 Like

Hm… good to know it’s working on the Mac. I thought it wouldn’t… LOL!

But the script is meant for be used in a folder full of .md files and the .sh should be in the same directory also.

We’re on the same distro. (high five!)

So can you tell me what you’ve tried so far? Are you getting any errors in the terminal?

It’s a simple little script, meant to be saved as a .sh then you need to make into an executable (see here for instructions)

Then you simple put your .md files into the same directory as the executable, open terminal from that folder and simply run ./

Yaay. Apparently, I’m trying to convert data files and not content files. I got these errors line 3: syntax error near unexpected tokenDIR="${FILE%.*}"' line 3: DIR="${FILE%.*}"

What is the extension of the data files? I think that if you replace .md with what you’re using the script should work.

But I haven’t tried that…

It’s .toml I tried that didn’t work for me.

OK. I just tested the script with .toml and to get it working you need to modify it like this:

for FILE in *.toml
  # remove the last dot and subsequent chars, then add new ext
  mkdir -p "$DIR"
  mv "$FILE" "$DIR"
find ./ -iname '*.toml' -execdir mv -i '{}' \;

Thanks this worked.

Just used this script on a big folder … Works great! Thanks!

1 Like

@onedrawingperday I can’t thank you enough, the script didn’t do all the magic but resolved a mess of 3,584 changed files with 13,242 additions and 15,833 deletions. :slight_smile:



Thanks a lot for this bash script.

1 Like

For Windows:

forfiles /m *.md /c "cmd /c md @fname"
forfiles /m *.md /c "cmd /c move @file @fname\"

or change the las tline to

forfiles /m *.md /c "cmd /c move @file @fname\"

1 Like

For Windows Useful cmd for windows-users. Converter to page/ and reverse; slug to filename and etc

1 Like

I’m on a mac, and used this variant for individual sets of files:

# Assumes bilingual files like
# Get the first argument which should be just the base filename
for FILE in $1*.md
  # get basename from .md file to make folder
  # get name with lang
  # get lang string

  # make the folder
  mkdir -p "$DIR"
  # move the files into the folder and rename
  mv "$FILE" "$DIR/index.$"

ls -la "$DIR"

You might notice it will do the mkdir for every loop, which is not needed but, because of the -p switch, the folder gets created on only the first iteration. So it creates it the first loop, then fails to create it on subsequent loops. It’s an assumption but, probably good enough.

I put that in a file in my content/pages folder, and set it to executable with:

> chmod +x

Then assuming there are two files like and, I ran it like this:

> ./ about

For more info on how this is working, look into “bash parameter substitution”.

If you are editing the script and want to figure out a variant, start out with echo instead of the mkdir and mv commands, so that you can see how the script is working. Like:

echo $DIR