Reputation: 23
In my music directory I have multiple duplicate files of both .mp3 and .flac format. Consider:
/dir1/music1.flac
/dir1/music1.mp3
/dir2/music1.mp3
/dir2/music2.MP3
/dir2/music2.flac
/dir2/music3.mp3
music1.flac and music1.mp3 in dir1 are the same song in different formats, but music1.mp3 in dir1 and dir2 may not be (same name, but released on different albums).
I wish to traverse multiple subdirectories finding files with an identical prefix but different extensions, and then delete just the mp3 files. As such, for the above directories, I'd be left with:
/dir1/music1.flac
/dir2/music1.mp3
/dir2/music2.flac
/dir2/music3.mp3
I've tried to use the find command with the logical AND, but to no avail. Some failures on my part:
find ./ -regex '.*\(mp3\|flac\)$'
find . -type f -name "*mp3" -and -name "*flac"
Any help is appreciated. I've solved similar problems with posted stackoverflow code on my own, but I'm stumped on this one. YOU GUYS ARE GREAT.
Upvotes: 2
Views: 454
Reputation: 1725
This will confirm the files that will be deleted:
find . -type f|sort|awk -F ":" '{match($1,"(.+)\\.[A-Za-z0-9]+$",base); if (base[1]==prev) {fordel=$1} else {fordel=null};if (base[1]) prev=base[1]; if(fordel) {print "\"" fordel "\""}}'|xargs echo
And this will handle the deletion:
find . -type f|sort|awk -F ":" '{match($1,"(.+)\\.[A-Za-z0-9]+$",base); if (base[1]==prev) {fordel=$1} else {fordel=null};if (base[1]) prev=base[1]; if(fordel) {print "\"" fordel "\""}}'|xargs rm
Both solutions will handle spaces in files.
Upvotes: 0
Reputation: 8064
Try this (Shellcheck-clean) code:
#! /bin/bash
shopt -s nullglob # Globs that match nothing expand to nothing
shopt -s globstar # ** matches multiple directory levels
for mp3_path in **/*.[Mm][Pp]3 ; do
# Find '.flac', '.FLAC', '.Flac', ..., files with the same base
flac_paths=( "${mp3_path%.*}".[Ff][Ll][Aa][Cc] )
if (( ${#flac_paths[*]} > 0 )) ; then
# There is a(t least one) FLAC file so remove the MP3 file
printf "Removing '%s'\\n" "$mp3_path"
# rm -- "$mp3_path"
fi
done
It requires Bash version 4.0 or later because it uses globstar
.
Since your example included both lower case and upper case '.mp3', the code handles any case of '.mp3' or '.flac'. It can be simplified if that is not necessary.
Remove the comment on the rm
line to make it actually remove files.
Upvotes: 3