1

I have a lot of folders, some with mp3 files only, others with m4a files only, other with files of both extensions.

I need to identify which folders have files in both extensions, then move the mp3 files to another folder, keeping just the m4a files. If the folder has some file that are not in both extensions, nothing should happen.

I'm exploring the shell for some time, but I'm not anywhere near being able to do something like that. If I have any progress, I'll update here anyway.

3

If I've understood this correctly then you just need to search for .mp3 files and move the ones for which an equivalent .m4a file exists in the same directory. The following bash script will do that, but it won't find duplicate MP3/M4A pairs of files that exist in different directories from each other. Note that it's important to get the quoting of variables correct because music files often have lots of spaces in their names and bash interprets spaces as separating items in lists.

#!/bin/bash

# Name of directory under which you music is stored.
SOURCE_DIR=/path/to/current/music/dir

# Name of directory you want to move the MP3s to.
DEST_DIR=/path/to/mp3/destination/dir

# Create the destination directory for the moved MP3s, if it doesn't already exist.
[ ! -d $DEST_DIR ] && mkdir -p $DEST_DIR

# Search for .mp3 files starting in $SOURCE_DIR
find $SOURCE_DIR -type f -name "*.mp3" | while read fin
do

  # Create the equivalent file name with .m4a extension.
  fm4a=${fin/.mp3/.m4a}

  # If a file with .m4a extension exists, move the .mp3 file to the destination dir.
  # In the event of a file name clash in the destination dir, the incoming file has
  # a number appended to its name to prevent overwritng of the existing files.
  [ -f "$fm4a" ] && mv -v --backup=numbered "$fin" $DEST_DIR/
done

##
## End of script.
##

Before running that version, I suggest replacing the line before done with the following line as a sort of dry run so you can get an idea of what will be moved:

  [ -f "$fm4a" ] && echo "Moving $fin to $DEST_DIR/"

(Cue comments correcting my dangerous use of find and while.)

2

mv will issue some file not found errors, but this should work

ls -1 *.m4a | sed 's#\(.*\).m4a#mv \1.mp3 otherdir#' | sh
  • I get a error ls: *.m4a: No such file or directory. I’m supposed to change something on the script? – NoneType Mar 5 '14 at 15:12
  • you have to run it in the directory that contains the .m4a and .mp3 files. (actually you didn't provide enough detail about your directory structure and how the files are distributed among the directories.) – Emery Lapinski Mar 7 '14 at 21:32
0

I can't think of a way to do it in the shell; and even if you could, it would be very limited when compared to what a program could achieve. I know for sure duplicate cleaner (digital volcano) can search for music files and move the mp3 version of any duplicate elsewhere. It does fuzzy matching too. http://download.cnet.com/Duplicate-Cleaner/3000-2248_4-10584403.html?part=dl-&subj=dl&tag=button watch the adware on install...

0

This solution was tested on /bin/bash from a GNU/Linux system. I'm assuming your mac has a /bin/bash for this, along with awk, tr, grep, ls, rm, and wc. (/bin/bash is the default shell executable). This script also assumes that you have ONLY mp3 and m4a files, and that some directories contain no mp3 and m4a files. (wrote it on the

Again, this is assuming that Mac has bash, tr, grep, ls, rm, and wc (standard UNIX utilities, iirc)

(sorry for bad scripting practices, I'm not very good at shell scripting)

(directory = folder)

(Specify the destination directory using the FIRST ARGUMENT) (i.e. ./thisscript.sh directoryname)

(before you do this, read through the whole post)

Create a text file in the parent directory of all those directories with the music in them and paste this in: http://pastebin.com/HcAvWtG0 Now navigate to that directory in the shell and type:

bash <filename>

Note that you can't do something as complicated like this without a script. ;)

Walking you through it:

#!/bin/bash

Tells us to use /bin/bash, the shell.

todir=$1

Parse the first argument as the destination directory and store it in $todir (a variable).

cd $( dirname $0 )

Just to make things safe so we can execute the script from any directory, as long as the script is in the same directory as all the directories of the music stuff.

DIRLIST=$( ls -F | grep '/' | tr -d '/' )

List the directories.

for DIR in $DIRLIST
do

Iterate through the directories.

    mp3num=$( ls $DIR | grep -c \\.mp3 )
    m4anum=$( ls $DIR | grep -c \\.m4a )
    filnum=$( ls $DIR | wc -l )

Store some variables we need (number of mp3's, number of m4a's, number of files

    echo $DIR $mp3num $mp4num $filnum

(for debugging only)

    if [ $DIR = $todir ]; then
        continue
    fi

If the directory we are looking at on the current iteration, skip it.

    if [ $m4anum = 0 -o $mp3num = 0 ]
    then
        continue

If the directory has no m4a's or no mp3's, skip it.

    elif [ $mp3num != 0 -a $m4anum != 0 ]
    then
        mv $DIR/*.mp3 $todir

If the directory has some mp3's and some m4a's, then move all the mp3's in the directory to the specified destination directory.

    fi
done

We're done.

The reason why this will probably work on macs as well is because macs are unix-based. They also have bash, which is the shell language we're using here, and all those little unix utilities (I looked them up and they appeared as the first result in Mac Manpages.)

Also, make sure that the destination directory EXISTS, or it won't work...

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.