Posted on December 3, 2022 | #bash, #blogathon2022

Un-dash filenames with Bash

TLDR; You can find the script on GitHub!

Recently I wanted to convert 3000+ tabler SVG icons into Astro components for my website. This also included adding Astro frontmatter into each file and exposing some of the SVG parameters.

What I want to focus on here are the filename transformations. What I need to do is this:

some-icon-name.svg 👉 SomeIconName.astro

Mostly for nice-looking import statements. But I’m also always down for a little bash scripting!

Battle plan


Getting rid of a file extension

This is easy enough and very common in Bash. The technique we will use is called parameter expansion. Suppose we have our filename stored in the FILE variable:

FILE=${FILE%.svg}

Split the name by the - character

Here a utility with the name tr will help us (abbreviation for “transliterate”).

FILE=$(echo $FILE | tr "-" " ")

Make an array out of the split filename

Here it comes in handy that we replaced the dashes with the space character in the previous step. Bash uses spaces as its default delimiter - and arrays are no exception. Here we can convert our variable into an array just by wrapping it in parentheses.

arr=($FILE)

This enables us to iterate over the split filename with a for loop, which we will use for the capitalization!


We can squeeze all 3 steps above into a single line nicely!

> arr=($(echo "${FILE%.svg}" | tr "-" " "))
> ```

---

## Capitalize the filename parts

Now we have parts stored in a bash array. We can iterate over them, capitalize each separately, and join them back together.

First, define a variable for the final transformed filename

```bash
capitalized=""

Loop over the name parts array

for NAMEPART in $arr; do
	# Our next code will go here
done

Take the first letter from our name part and make it uppercase. The tr utility uses UNIX character class notation instead of a more familiar regex.

tr '[:lower:]' '[:upper:]' <<< ${NAMEPART:0:1}

Capture the output of the above command, append the rest of the word and store it in a variable! This boils down to this line:

NAMEPART="$(tr '[:lower:]' '[:upper:]' <<< ${NAMEPART:0:1})${NAMEPART:1}"

Now just append the transformed name part to the resulting capitalized file name! The entire process now looks like this

capitalized=""
for NAMEPART in $arr; do
  NAMEPART="$(tr '[:lower:]' '[:upper:]' <<< ${NAMEPART:0:1})${NAMEPART:1}"
  capitalized=$capitalized$NAMEPART
done

Add your own file extension!

After all, we’ve gone through, this part is a piece of cake 🍰

capitalized=${capitalized}.astro

Final notes

Don’t underestimate Bash, it is almost like a superpower. It was made for string operations and file handling, so naturally, it’s pretty damn good at it.

Although I’m sure there is a more efficient way to do this. It transformed 3036 files in less than 19 seconds (+ some writing into the actual files). Not bad!

 time ./convert-astro.sh
./convert-astro.sh  6.17s user 17.48s system 125%cpu 18.869 total
 ls icons-astro | wc -l
    3036

I used this procedure in my actual script, with which I converted raw SVG icons into my own Astro components. You can find the script on GitHub!