查找和删除具有相同前缀但不同扩展名的文件(即 *.flac 和 *.mp3)

Finding and deleting files with same prefix but different extension (i.e., *.flac and *.mp3)

在我的音乐目录中,我有多个 .mp3 和 .flac 格式的重复文件。考虑:

/dir1/music1.flac
/dir1/music1.mp3
/dir2/music1.mp3
/dir2/music2.MP3
/dir2/music2.flac
/dir2/music3.mp3

music1.flac和dir1中的music1.mp3是同一首不同格式的歌曲,但dir1和dir2中的music1.mp3可能不是(同名,但发布在不同的专辑中)。

我想遍历多个子目录,找到前缀相同但扩展名不同的文件,然后只删除 mp3 文件。因此,对于上述目录,我会留下:

/dir1/music1.flac
/dir2/music1.mp3
/dir2/music2.flac
/dir2/music3.mp3

我试过将查找命令与逻辑与一起使用,但无济于事。我的一些失败:

find ./ -regex '.*\(mp3\|flac\)$'
find . -type f -name "*mp3" -and -name "*flac"

感谢任何帮助。我已经用自己发布的 Whosebug 代码解决了类似的问题,但我对这个问题感到困惑。你们太棒了。

这将确认将要删除的文件:

find . -type f|sort|awk -F ":" '{match(,"(.+)\.[A-Za-z0-9]+$",base); if (base[1]==prev) {fordel=} else {fordel=null};if (base[1]) prev=base[1]; if(fordel) {print "\"" fordel "\""}}'|xargs echo

这将处理删除:

find . -type f|sort|awk -F ":" '{match(,"(.+)\.[A-Za-z0-9]+$",base); if (base[1]==prev) {fordel=} else {fordel=null};if (base[1]) prev=base[1]; if(fordel) {print "\"" fordel "\""}}'|xargs rm

两种解决方案都可以处理文件中的空格。

试试这个(Shellcheck-clean)代码:

#! /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

它需要 Bash 4.0 或更高版本,因为它使用 globstar

由于您的示例同时包含小写和大写“.mp3”,因此代码可以处理“.mp3”或“.flac”的任何大小写。如果不需要的话可以简化。

删除 rm 行的注释,使其真正删除文件。