1

I have a list of mp3 files named like so:

$artist/$album ($year)/$tracknum $title.mp3

Many of these tracks have incorrect or missing tags, which I am correcting through the use of id3v2 and regex because the file names are all correct. Here is an example of how I'm setting titles:

for mp3 in *.mp3; do id3v2 -t "$(echo $mp3 | cut -d. -f1 | cut -d\  -f2-)" "$mp3"; done

(Note: quotes are there because the titles often have spaces, which causes bash to complain unless spaces are used)

My question is this: is there a better way to extract a specific substring from these files? In the case of the titles, I can't use grep -o without also matching $tracknum because many tracks have numbers and spaces in the titles (meaning that I'd need "([0-9a-zA-Z ]+)" for my pattern, which matches the entire filename before the .mp3).

I'm almost certain that there is a much better way to do this. Is there?

1

If you want to extract the title (and, in case it's useful, the tracknum), you should be able to do it like this:

read -r tracknum title <<<$(basename "$mp3" .mp3)

For the other bits, I'd start by splitting the filename by / to isolate the parts. For example:

album_year=$(cut -d/ -f2 <<<"$mp3")
album=${album%\ (*)}
year=${album_year:-5:4}

The last one is dependent on the year actually being present and four digits long; if that's not guaranteed then you could do it using a more clumsy expression:

year=${album_year:$((${#album}+2)):$((${#album_year}-${#album}-3}

Also, if you don't know how deep in the path the album_year part is, you can extract the second last segment (i.e. the immediate directory of the file) with:

album_year=$(basename "$(dirname "$mp3")")

Or, you can split the entire path into an array:

IFS=/ read -ra segments <<<"$mp3"
album_year=${segments[-2]}
  • I had to reverse the path string (it's the complete path from /) before passing it to cut, but this was overall very helpful. – J David Smith Aug 5 '13 at 21:59
  • 1
    @J.DavidSmith: You could have just adjusted the -f2 to the actual depth :) I added another way to get the second last component of a filepath. – rici Aug 5 '13 at 23:39
  • If I could upvote your answer again I would. – J David Smith Aug 5 '13 at 23:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.