Skip to content
/ tag-mp3 Public

An evening/night challenge. I learned to use `awk`

Notifications You must be signed in to change notification settings

t-h2o/tag-mp3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MP3 tag with file name

I have recently downloaded the discography of Bob Marley through torrent and there is all the metadata within the torrent file, but not in the mp3 one. My goal is to collect the file name to tag the mp3 files.

1. My approach of creating my script

1.1. Find a scripting language

For this kind of use (file manipulation), the bash script is a good choice.

1.2. Collect data

1.3. Scanf

I already know about scanf function as I have used it in the C language. You give scanf a pattern` and it collects the data. I’m looking for something like scanf for bash script.

I found on reddit an example.

#!/bin/bash

pattern="Fan: (.+) rpm CPU die temperature: (.+) C"
if [[ "Fan: fann rpm CPU die temperature: 42 C" =~ $pattern ]]; then
    fan=${BASH_REMATCH[1]}
    cpu=${BASH_REMATCH[2]}
fi
echo "$fan" "$cpu"
I use shellcheck to get good practices for creating shell scripts.

1.4. A loop through each file

I need a loop through each file. I found an example on w3guides.com

#!/bin/bash

for filename in ./*; do
    echo "${filename}"
done

1.5. Parse the filename

For each track on an album, we have to collect:

  • The title

  • The track number

We already have:

  • The artist

  • The album

  • The yar

Example of filename for Keep On Skanking:

01 - All In One.mp3
02 - Keep On Moving.mp3
03 - Keep On Skanking.mp3
04 - Shocks Of Mighty (Soul Almighty Ve.mp3
05 - Brand New Second Hand.mp3
06 - Jungle Dub.mp3
07 - Satisfy My Soul Babe (Version).mp3
08 - Dracula (Version).mp3
09 - Vs. Lee Scratch Perry Dreamland (Featuring Bunny Wailer).mp3
10 - Comma Comma.mp3

1.6. awk

After, a few researches I once again found this dark tool. I have had chosen to never learn to use this, because it’s a very hard tool.

NAME
       awk — pattern scanning and processing language

1.6.1. Print the track number

For each .mp3 files:

#!/bin/bash

for filename in ./\.*mp3; do
    echo "${filename}"
    echo "${filename}" | \
        awk '{printf "Track number: %d\n", substr($1, 3)}'
done

# OUTPUT:
# ./01 - All In One.mp3
# Track number: 1

If I take this filename as example ./01 - All In One.mp3. The first element is ./01. I have to do a substring, so begin my substring to the third character.

I find it weird, this time the index start with 1 and not 0.

With the substring I get 01 instead of ./01. And then I use %d of printf for convert to a number.

1.6.2. Print the track title

#!/bin/bash

for filename in ./*\.mp3; do

    echo "${filename}"
    echo "${filename}" | \
        awk '{printf "Titel: " }{i = 3} \
        {while (i + 1 <= NF ) {printf "%s ", $i; i++}} \
        {printf "%s\n", substr($i, 0, length($i) - 4)}'
done

# OUTPUT:
# ./01 - All In One.mp3
# Title: All In One
  1. Just print "Title: ".

  2. Set i = 3.

  3. While (i + 1 ⇐ NF) print each element.

NF: The number of fields in the current record.
  1. Remove ./mp3: Substing of the last element, start a the beginning of the string, stop at the end minus four.

2. Tag the track

It’s the simplest step, after saving track and title. Just use mp3info for tagging them.

#!/bin/bash

for filename in ./*\.mp3; do

    track=$(echo "${filename}" | awk '{printf "%d", substr($1, 3)}')
    title=$(echo "${filename}" | \
        awk '{i = 3} {while (i + 1 <= NF ) {printf "%s ", $i; i++}} \
        {printf "%s", substr($i, 0, length($i) - 4)}')
    printf "Track: %s\tTitle: %s\n" "${track}" "${title}"
    mp3info -t "${title}" -n "${track}" "${filename}"
done

3. Bonus: Collect the folder data

We have to collect from the folder

  • The artist

  • The year of the album

  • The album name

The tracks are tidied up like this:

Bob Marley - 1967 - Keep On Skanking
├── 01 - All In One.mp3
├── 02 - Keep On Moving.mp3
└── [...]
Bob Marley - 1970 - African Herbsman
├── 01 - Riding High.mp3
├── 02 - Lively Up Yourself.mp3
└── [...]

For remove the ./ or ./${foldername}, we can use basename.

4. The final script

#!/bin/bash

for folder in ./Bob*; do

    folder=$(basename "${folder}")
    artist="Bob Marley"
    year=$(echo "${folder}" | awk '{printf "%d", $4}')
    album=$(echo "${folder}" | awk '{i = 6} {while (i <= NF ) {printf "%s ", $i; i++}}')

    for filepath in "${folder}"/*\.mp3; do

        filename=$(basename "${filepath}")

        track=$(echo "${filename}" | awk '{printf "%d", $1}')
        title=$(echo "${filename}" | \
        awk '{i = 3} {while (i + 1 <= NF ) \
        {printf "%s ", $i; i++}} \
        {printf "%s", substr($i, 0, length($i) - 4)}')

        mp3info -a "${artist}" \
            -l "${album}" \
            -y "${year}" \
            -t "${title}" \
            -n "${track}" "${filepath}"

        echo mp3info -a "${artist}" \
            -l "${album}" \
            -y "${year}" \
            -t "${title}" \
            -n "${track}" "${filepath}"
    done
done

5. Conclusion

As I said awk is a dark and a complicated tool. But after spending a few hours reading manuals and manipulating awk, I got comfortable with it. With this project I learned basics of awk and new knowledge on AsciiDoc and bash.

5.1. The real conclusion

All the Bob Marley’s tracks are tagged and tidied !

cmus view

6. Other

6.1. Pattern matching

  1. Use the bash shell

  2. Enable the extglob

shopt -s extglob
  1. Try to list all but not MP3 files with

ls !(*.mp3)

About

An evening/night challenge. I learned to use `awk`

Topics

Resources

Stars

Watchers

Forks

Languages