查找和删除具有相同前缀但不同扩展名的文件(即 *.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
行的注释,使其真正删除文件。
在我的音乐目录中,我有多个 .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
行的注释,使其真正删除文件。