繁体   English   中英

将mp3文件从一个目录移动到按艺术家,专辑,歌曲名称的单独目录

[英]Move mp3 files from one directory to separate directories by artist, album, song name

我在一个文件夹中备份了所有mp3文件。

是否会有bash命令自动将所有文件自动移动到自己创建的乐队专辑标题目录中?

如您在图像中看到的,破折号前的第一个单词是歌手姓名,然后是专辑名称,然后是歌曲名称。

在此处输入图片说明

示例:艺术家或乐队-专辑标题-song.mp3的名称。

因此,最后,文件将处于以下层次结构中。

Artist or band1/    
        album title1/
                name of song.mp3
        album title2/
                name of song.mp3    

Artist or band2/
        album title1/
                name of song.mp3

等等。

我不知道直接执行此操作的命令,但是这是我(使用Perl)解决此问题的方法:

perl -MFile::Path -we 'for my $file (glob "*.mp3") { my ($artist, $album, $title) = split / - /, $file, 3; mkpath "$artist/$album"; my $new = "$artist/$album/$title"; rename $file, $new or warn "$file -> $new: $!\n"; }'

或者更具可读性:

perl -MFile::Path -we '
    for my $file (glob "*.mp3") {
        my ($artist, $album, $title) = split / - /, $file, 3;
        mkpath "$artist/$album";
        my $new = "$artist/$album/$title";
        rename $file, $new or die "$file -> $new: $!\n";
    }'

我会在Bash中执行以下操作:

#!/bin/bash

# Set field separator to dash
IFS=-

# Loop over mp3 files
for song in *.mp3; do

    # Read long name into dash separated array
    read -a songinfo <<< "$song"

    # Remove trailing space from band name
    band=${songinfo[0]% }

    # Remove trailing and leading space from album name
    album=${songinfo[1]% }
    album=${album# }

    # Remove leading space from song title
    title=${songinfo[2]# }

    # Make band/album directory, don't complain if they exist already
    mkdir --parents "$band/$album"

    # Move and rename song
    mv "$song" "$band/$album/$title"
done

这将更改IFS变量,但是由于它将在子进程中运行,因此我无需费心将其重置为其原始值。

由于用于扩展空格的参数扩展,它有点长,并且如果在乐队/专辑/歌曲名称之间的其他地方没有破折号,则它当然会中断。 有关在其他地方也可以使用破折号的Bash解决方案,请参见mklement0的答案

melpomene强大而有效的Perl解决方案是最好的解决方案。

这里是一个纯粹的Bash实现(除调用外部公用事业mkdirmv ),这也是相对于避免假稳健-阳性:

for fname in *.mp3; do
  IFS=/ read -r artist album song <<<"${fname// - //}"
  song="${song//// - }"
  mkdir -p "$artist/$album"
  mv "$fname" "$artist/$album/$song"
done
  • ${fname// - //}使用Bash参数扩展将所有( //<space>-<space>序列替换为( / )a / char。 每。

    • 这样做的原因替代是bash的令牌分配机构可以通过单个字符(其中一个数)只有分裂。
    • 选择辅助分隔符/是因为它保证不会包含在输入文件名中。
  • 结果通过此处字符串( <<<read $IFS (内部字段分隔符)设置为辅助分隔符/ ,以便将文件名拆分为其组成标记。
    请注意,通过指定3个变量名称,指定的最后一个变量将接收输入的其余部分,即使它包含分隔符的其他实例。

  • 为了安全起见, song="${song//// - }"然后将/实例转换回<space>-<space>序列,以便最终保留未修改的歌曲部分(如果包含这样的序列)。

  • mkdir -p "$artist/$album"然后为艺术家和专辑创建子文件夹; 请注意,如果目标文件夹已存在,则mkdir -p是(成功)无操作。

  • 最后, mv命令将输入​​文件以其仅具有歌曲标题的名称移动到目标文件夹。

bash解决方案,还要考虑艺术家名称( All-Time Quarterback )中也出现了dash(-) )。

#!/bin/bash
ls *.mp3 > /home/user/mp3songs.list
awk '{print "\""$0"\""}' /home/user/mp3songs.list

while read -r line; do
song="$line"
artist=`echo "$song"|awk -F" - " '{print$1}'`
title=`echo "$song"|awk -F" - " '{print$2}'`
name=`echo "$song"|awk -F" - " '{print$3}'`
mkdir -p "$artist"
mkdir -p "$artist"/"$title"
printf "Moving $song to $artist/$title directory"
mv "$song" "$artist"/"$title"/"$name"
done < /home/user/mp3songs.list

rm /home/user/mp3songs.list

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM