Rename subfolder: add leading word from parent folder

847 Views Asked by At

I have a large music library organized in Artist folders with Album subfolders:

Artist 1
- Album A
-- File 1
-- File 2
- Album B
-- File 1
-- File 2
Artist 2
- Album C
-- File 1
-- File 2
- Album D
-- File 1
-- File 2

Now I want to rename all Album folders by adding the Artist name as prefix AND move all Album folders in to the root directory, like this:

Artist 1 - Album A
- File 1
- File 2
Artist 1 - Album B
- File 1
- File 2
Artist 2 - Album C
- File 1
- File 2
Artist 2 - Album D
- File 1
- File 2

What is the best way to do that? I tried to do it with Total Commander, but I don't get it. Or maybe shell, mp3tag? I use Windows 10. Thanks!

2

There are 2 best solutions below

0
Jörg Steinhauer On BEST ANSWER

I found an answer by myself. The best way to do it is to use mp3tag tool. You can create new folders and copy your files in it.

  1. Select Converter > Tag - Filename

  2. Type in:

    E:\%artist% - %album%\$num(%track%,2) - %title%
    

You'll receive a directory with Artist - Albumname\01 - File.mp3

1
Lutarisco On

This could be done in several ways, actually. I'll show how in bash, but that's only if you have that thing of Bash on Ubuntu on Windows. Again:

BASH

Assuming that your music library is ~/Music/, that all the artist folders are inside, that you accept to have everything moved to a new folder, assuming that it doesn't yet exist (because if you had an artist folder named 'CoolSinger' and just accidentally you also have another artist folder named 'CoolSinger - CoolAlbum', by a mistake, there would be problems...), and that there are not any other files involved than what you state, the shell script would look like this:

#!/bin/bash

mkdir ~/NewMusic/
for artistdir in ~/Music/*; do
  artistname="$(basename "${artistdir}")"
  for albumdir in "${artistdir}"/*; do
    albumname="$(basename "${albumdir}")"
    mv "${albumdir}" ~/NewMusic/"${artistname} - ${albumname}" 2>/dev/null
  done
done

And let me explain it in human:

Create the destination folder. Then, for every artist (assuming all are folders); iterate through every album sub-folder, moving it to the new folder, and renaming it, by the way, using the artist name and folder name from the actual folder names. If everything went OK, this would result in:

  • A folder ~/Music/ with the original sub-folder names, but they're now empty.
  • A folder ~/NewMusic with the desired structure.
  • If an artist folder is empty, the shell would try to throw an error because it expands to the literal string (explained later), but don't worry, because if it is empty, then anything is to do with it, so you can ignore it, appending 2>/dev/null to the command. However, if anything else goes wrong with this, it will also be silenced.

If you wanted to, let's say, stay with the original files, and have a copy of all that with the desired structure, you should change the mv command for a cp -R one.

And all that is for a script, in a file. If you wanted to execute it right from the command line, which would make somewhat tricky to change the folder name for the music library, it would look like this:

mkdir ~/NewMusic/; for artistdir in ~/Music/*; do artistname="$(basename "${artistdir}")"; for albumdir in "${artistdir}"/*; do albumname="$(basename "${albumdir}")"; mv "${albumdir}" ~/NewMusic/"${artistname} - ${albumname}"; done; done

And an explanation of everything there:

  1. mkdir creates the directory.
  2. for A in B ; do C ; done is a loop. It loops through every string separated by one of the IFS characters in B, and assign it as a value for the variable A, while it executes C.
    • Note that the text in the script has an asterisk. The shell expands a string with an asterisk to what it finds to match the pattern. For instance, if you had a bunch of Word documents, typing echo *.docx would expand to every name matching that ending, in the current folder (in another case, echo /path/*.docx).
  3. So, for every folder inside the specified directory, assign (once for every artist folder) the variable artistname with the base name of the file specified (in this case, the folder) as its value. So, basename /path/to/anything returns anything.
  4. With the help of another for loop, do for every element inside the artist directory, rename it as specified, and if the new name is in another directory, it will move it there.
    • Again, the 2>/dev/null redirection is there to redirect all output in stderr to the void. Output in stdout would be still printed, though, if there was any.

SOME IMPORTANT NOTES

  • I don't have any idea whether the shell from Bash on Ubuntu on Windows detects /dev/null as the special character file that a standard UNIX machine has or not. Likely it does, or it wouldn't be compatible with so many things.
  • This is only if you have Bash on Ubuntu on Windows in your Windows 10. If I recall correctly, the chance of using it was implemented with the Anniversary Update. If you have the update, but not bash, I recommend you to install it. There are several guides over that on the Internet.
  • About the folder structure. I suspect the same about /dev/null as for the POSIX folder structure: that it follows it, as it's not just Bash on Windows, but Bash on Ubuntu on Windows.