我在一个文件夹中备份了所有mp3文件。
是否会有一个bash命令来自动移动他们自己的乐队相册标题目录中的所有文件,这些文件将在动态创建?
正如您在图片中看到的那样,破折号之前的第一个单词是艺术家姓名,然后是专辑标题,然后是歌曲的名称。
示例:艺术家或乐队 - 专辑标题 - 歌曲名称.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
等等。
答案 0 :(得分:3)
我不知道直接执行此操作的命令,但这是我将如何解决此问题(使用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";
}'
答案 1 :(得分:1)
我会在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's answer。
答案 2 :(得分:1)
melpomene's robust and efficient Perl solution是最佳解决方案。
这是一个纯粹的Bash实现(除了对外部实用程序mkdir
和mv
的调用之外),它在避免错误-
肯定方面也很强大:
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>
个序列替换为/
)/
个字符。每个
/
,因为它保证不会包含在输入文件名中。结果通过here-string(read
)传递给<<<
; $IFS
,内部字段分隔符,设置为辅助分隔符/
,以便将文件名拆分为其成分标记。
请注意,通过指定 3 变量名称,指定的最后一个变量将接收输入的其余部分,即使它包含分隔符的其他实例。
为了安全起见,song="${song//// - }"
然后将/
的实例转换回<space>-<space>
序列,以便最终保留未修改的歌曲部分,如果它包含此类序列。< / p>
mkdir -p "$artist/$album"
然后为艺术家和专辑创建子文件夹;请注意,如果目标文件夹已存在,mkdir -p
是一个(成功的)无操作。
最后,mv
命令将输入文件移动到其歌曲标题名称下的目标文件夹。
答案 3 :(得分:0)
bash解决方案,同时考虑到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