Shell script to copy Music/Artists/Albums/Songs to Music2/Artists/Songs

Hi,


My Music folder is currently organized as follows (standard iTunes behaviour):



Music
Artists Albums
Songs
Artist1 Album1 Song11
Song12
Song13
Album2 Song21
Song22
Artist2 Album1 Song11
Song12
Album2 Song21
Song22
Song23

etc.


I would like to copy this Music Folder to an USB flash drive, but without the "Albums" level, i.e.:



Music2
Artists
Songs
Artist1

Song11

Song12
Song13
Song21
Song22
Artist2 Song11
Song12
Song21
Song22
Song23


I assume that an unix shell script is able to do this, but this is beyond my skills😟

Or do you know a software that can manipulate files in such a way?

Thanks in advance.

Posted on Jul 31, 2013 10:19 PM

Reply
8 replies
Sort By: 

Aug 3, 2013 12:06 PM in response to Cemoi

There are many ways to do this, ranging from the simple (no error checking, best of luck) to incredibly complex, checking for errors, duplicates, etc.


For the simple, something like:


cd /Music/Artist1

mv */.*m4a .

find . -type d --delete


These three steps first change to the relevant artist's directory (substitute the appropriate directory path, and you'll need to repeat this for each artist... to iterate through each artist takes a lot more work), then it moves (via mv) all files from all subdirectories into the artist directory. Once the mv has done you can delete all the directories (using find to identify them).

The script is very simple - it doesn't take account of multiple levels of subdirectories (e.g. if there was a subdiretory within the Album directory for some reason), It also only copies .m4a files, so if there are other files in the directory they won't be copied (but a simple change to the mv command would fix that).

Reply

Aug 3, 2013 3:45 PM in response to Cemoi

Audio filenames not only contain spaces in their name but special characters normally reserved for the shell- ( ) " ' [ ] & . The following should handle these special characters. I'm not sure if your locale will work with xargs. You may need to change LC_LANG and LC_ALL to C.


First copy the entire $HOME/Music/iTunes/iTunes\ Media/Music directory to the thumb drive. Drag and drop with the Finder.app. Open the Terminal.app type the following commands. Note the "#..." are comments you should not type them. BTW- this solution is painfully slow.


#  move to the Music directory on the thumb drive
#  change <Volume Name> to the thumb drive's volume name

cd "/Volumes/<Volume Name>/Music"

#  Move audio files .mp3 and .m4a to the artist directory
#  without overwriting files with the same name

ls | while read dir; do
    find "${dir}" -type f \( -name "*.mp3" -o -name "*.m4a" \) -print0 | xargs -0 -I '{}' mv -n "{}" "${dir}"
done

#  Rename duplicate filenames [ALBUM.NAME_ORIGINAL.FILENAME] and move the files

find . -type f \( -name "*.mp3" -o -name "*.m4a" \) -mindepth 3 | while read file; do
     base=${file%\/*}
     base=${base##*\/}
     mv "${file}" "${file%*\/*\/*}"/"$base"_"${file##*\/}"
done

#  Remove any empty directories

find . -type d -empty -delete


Message was edited by: Mark Jalbert

Reply

Aug 4, 2013 3:43 AM in response to Mark Jalbert

Thanks Mark, two questions before I try it:

- should the multiple line commands be typed one line at a time, followed by Enter, or should I copy/paste several lines to the terminal prompt?

- what is the point in "

without overwriting files with the same name
"? Does it assume I may already have Songs at the Artist directory level (which is not the case)?

Reply

Aug 4, 2013 4:34 AM in response to Cemoi

- should the multiple line commands be typed one line at a time, followed by Enter, or should I copy/paste several lines to the terminal prompt?

Yes, type each line followed by Enter or you can copy/paste several lines to the terminal prompt. The first command must be typed with the proper mountpoint in the /Volumes directory. Follow each code block in the exact order. You must use a posix-compliant shell such as ksh, zsh, or bash. I tested the code blocks in ksh and zsh.


- what is the point in "

without overwriting files with the same name
"? Does it assume I may already have Songs at the Artist directory level (which is not the case)?

The assumption is an Artist's albums may contain the same filename.

Reply

Aug 4, 2013 5:35 AM in response to Mark Jalbert

I'm using bash.


I tried it and it worked almost fine:

- I got many "no such file or directory" warning messages, e.g. "mv: Stoa/Porta VIII/._Luvah.m4a: No such file or directory",

- after the last step, most but not all empty "Album" directories were removed. I can easily remove them by hand, but strange...

Reply

Aug 4, 2013 6:02 AM in response to Cemoi

- I got many "no such file or directory" warning messages, e.g. "mv: Stoa/Porta VIII/._Luvah.m4a: No such file or directory",

The ._FILENAME is a HFS file fork containing metadata. You copied the Music directory to a msdos filesystem.


- after the last step, most but not all empty "Album" directories were removed. I can easily remove them by hand, but strange...

Not really, those remaining directories more than likely contain .DS_Store files (hidden from the Finder.app). Thus the directories were not empty.

Reply

Aug 4, 2013 6:26 AM in response to Mark Jalbert

The ._FILENAME is a HFS file fork containing metadata. You copied the Music directory to a msdos filesystem.

OK, clear. For future runs, should I be better off runing the command in a directory on my Mac, and copy the resulting music folder to the USB drive?


Not really, those remaining directories more than likely contain .DS_Store files (hidden from the Finder.app). Thus the directories were not empty.


OK. I removed them manually, which took me less than one minute. Should I add a "rm -r .DS_Store" step before future runs?

Reply

Aug 10, 2013 10:41 AM in response to Cemoi

OK, clear. For future runs, should I be better off runing the command in a directory on my Mac, and copy the resulting music folder to the USB drive?

No, the optimum solution would be to format the thumb drive with the HFS+ filesystem. You could use cp, ditto, or rsync will the proper options and not copy the file fork to the thumbdrive. Or you could filter out the file forks in the two find commands.

ls | while read dir; do
    find "${dir}" -type f ! -name "._*" \( -name "*.mp3" -o -name "*.m4a" \) -print0 | xargs -0 -I '{}' mv -n "{}" "${dir}"
done

find . -type f ! -name "._*" \( -name "*.mp3" -o -name "*.m4a" \) -mindepth 3 | while read file; do
     base=${file%\/*}
     base=${base##*\/}
     mv "${file}" "${file%*\/*\/*}"/"$base"_"${file##*\/}"
done


The warning or error messages are innocuous anyways.

OK. I removed them manually, which took me less than one minute. Should I add a "rm -r .DS_Store" step before future runs?

I wouldn't bother. Change->


find . -type d -empty -delete

to


find . -type d -mindepth 2 -maxdepth 2 -exec rm -rf '{}' '+'
Reply

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Shell script to copy Music/Artists/Albums/Songs to Music2/Artists/Songs

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.