简体   繁体   English

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

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

I have a backup of all my mp3s files in one folder. 我在一个文件夹中备份了所有mp3文件。

Would there be a bash command to automatically move all files in their own band-album title directories that would be created on the fly? 是否会有bash命令自动将所有文件自动移动到自己创建的乐队专辑标题目录中?

As you can see in the image, first words before dash are artist names, then comes the album title, then comes the name of the song. 如您在图像中看到的,破折号前的第一个单词是歌手姓名,然后是专辑名称,然后是歌曲名称。

在此处输入图片说明

Example: Artist or band - album title - name of song.mp3. 示例:艺术家或乐队-专辑标题-song.mp3的名称。

So in the end, files would be in the following hierarchy. 因此,最后,文件将处于以下层次结构中。

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

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

and so forth. 等等。

I don't know of a command to do this directly, but here's how I would solve this (using Perl): 我不知道直接执行此操作的命令,但是这是我(使用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"; }'

Or slightly more readable: 或者更具可读性:

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";
    }'

I would do it as follows in Bash: 我会在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

This changes the IFS variable, but since this will be running in a child process, I didn't bother resetting it to its original value. 这将更改IFS变量,但是由于它将在子进程中运行,因此我无需费心将其重置为其原始值。

It's a bit lengthy due to parameter expansions to remove spaces, and it of course breaks if there is a dash in places other than between band/album/song names. 由于用于扩展空格的参数扩展,它有点长,并且如果在乐队/专辑/歌曲名称之间的其他地方没有破折号,则它当然会中断。 For a Bash solution that also works with dashes in other places, see mklement0's answer . 有关在其他地方也可以使用破折号的Bash解决方案,请参见mklement0的答案

melpomene's robust and efficient Perl solution is the best solution. melpomene强大而有效的Perl解决方案是最好的解决方案。

Here's a pure Bash implementation (except for calls to external utilities mkdir and mv ) that is also robust with respect to avoiding false - positives: 这里是一个纯粹的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// - //} uses Bash parameter expansion to replace all ( // ) <space>-<space> sequences with ( / ) a / char. ${fname// - //}使用Bash参数扩展将所有( //<space>-<space>序列替换为( / )a / char。 each. 每。

    • The reason for this substitution is that Bash's token-splitting mechanism can only split by (one of several) single characters. 这样做的原因替代是bash的令牌分配机构可以通过单个字符(其中一个数)只有分裂。
    • Auxiliary separator / was chosen because it is guaranteed not to be contained in the input filenames. 选择辅助分隔符/是因为它保证不会包含在输入文件名中。
  • The result is fed to read via a here-string ( <<< ); 结果通过此处字符串( <<<read $IFS , the internal field separator, is set to the auxiliary separator / in order to split the filename into its constituent tokens. $IFS (内部字段分隔符)设置为辅助分隔符/ ,以便将文件名拆分为其组成标记。
    Note that by specifying 3 variable names, the last variable specified receives the remainder of the input, even if it contains further instances of the separator. 请注意,通过指定3个变量名称,指定的最后一个变量将接收输入的其余部分,即使它包含分隔符的其他实例。

  • To be safe, song="${song//// - }" then converts instances of / back to <space>-<space> sequences, so as to ultimately preserve the song part unmodified, should it contain such sequences. 为了安全起见, song="${song//// - }"然后将/实例转换回<space>-<space>序列,以便最终保留未修改的歌曲部分(如果包含这样的序列)。

  • mkdir -p "$artist/$album" then creates subfolders for the artist and album; mkdir -p "$artist/$album"然后为艺术家和专辑创建子文件夹; note that mkdir -p is a (successful) no-op if the target folder already exists. 请注意,如果目标文件夹已存在,则mkdir -p是(成功)无操作。

  • Finally, the mv command moves the input file to the target folder under its song-title-only name. 最后, mv命令将输入​​文件以其仅具有歌曲标题的名称移动到目标文件夹。

bash solution , to also take point into consideration that dash(-) is also present in the artist names( All-Time Quarterback ). 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.

相关问题 将文件从一个目录移动到另一个目录,并添加到新目录中的每个文件名 - Move files from one dir to another and add to each files name in the new directory 使用 Paramiko 将文件从一个目录移动到另一个目录 - Move files from one directory to another with Paramiko 如何从单独的目录创建单独的tar文件并将其复制到/ tmp目录 - How to create separate tar files from separate directories and to copy to /tmp directory 删除 python 中名称相似的较小 mp3 文件 - delete smaller mp3 files with similar name in python 如何通过在目录及其子目录中递归搜索来随机播放 .mp3 歌曲? - How to play .mp3 songs randomly by searching for them recursively in a directory and its sub directories? 基于文件名的目录,然后将关联文件移动到正确的目录以获取随机名称 - directories based on the filename and then move the associated files to the correct directories for random name 将多个目录中的文件重命名为目录名称 - Rename files in multiple directories to the name of the directory 如何以编程方式或通过命令行(linux)设置歌曲的“专辑艺术家” - How do I set “Album Artist” of a song programmatically or through command line (linux) 将多个目录中的文件复制到一个目录中 - Copy files within multiple directories to one directory 如何将所有文件从一个目录移动(并覆盖)到另一个目录? - How to move (and overwrite) all files from one directory to another?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM