如何将文件名提取为两部分,一部分放入目录,另一部分放入目录?

How do I extract a file name into 2 parts, making one into directory and the other one inside of it?

我正在尝试按艺术家和姓名对所有 mp3 文件进行排序。目前,它们在 1 个巨大的文件名中。 例如艺术家 - 歌曲名称.mp3 我想将其转换为 Artist/Song 名称.mp3

以下是我目前尝试过的方法。在这种情况下,我使用的是名为 "hi\ -\ hey":

的测试文件
#!/bin/bash
# filters by all .mp3 extensions in the current working directory 
for f in *.mp3; do
# extract artist and song name and remove spaces
        artist=${f%  -*}
        song=${f#*-  }
#make directory with the extracted artist name and move + rename the file into the directory
        mkdir -p $artist
        mv $f $artist/$song;
done

出于某种原因,它创建了一个目录,其中包含歌曲名称而不是艺术家,此外还有大量错误:

mv: cannot move 'hey.mp3' to a subdirectory of itself, 'hey.mp3/hey.mp3'
mv: cannot stat 'hi': No such file or directory
mv: cannot stat '-': No such file or directory
mv: 'hey.mp3/hi' and 'hey.mp3/hi' are the same file
mv: cannot stat '-': No such file or directory

假设有很多文件,使用管道而不是 for 循环执行此操作可能要快得多。这具有避免复杂的 bash 特定语法和使用核心 unix/linux 命令行程序的额外优势。

find *-*.mp3 |
  sed 's,\([^-]\+\)\s*-\s*\(.*\),mkdir -p ""; mv "&" ""/"",' |
  bash

解释:

find查找当前目录下所有匹配-.mp3的文件

sed 命令将每一行更改为命令字符串,例如:

aaa - bbb.mp3
->
mkdir -p "aaa"; mv "aaa - bbb.mp3" "aaa"/"bbb.mp3"

bash 命令运行每个命令字符串。

你可以试试这个。

#!/usr/local/bin/bash
for f in *.mp3
do
artist=`echo $f | awk '{print }' FS=-`
song=`echo $f | awk '{print }' FS=-`
mkdir -p $artist
mv $artist-$song $song
mv $song ./$artist
done

这里我使用了两个变量艺术家和歌曲。因为你的测试文件名是 "hi\ -\ hey" 所以我将 awk 分隔符更改为“-”以根据它存储变量。

我们不需要使用 awk..通过使用 bash 参数扩展....它正在工作。

#!/usr/local/bin/bash
for f in *.mp3
do
artist=`echo ${f%-*}`
song=`echo ${f#*-}`
mkdir -p $artist
mv $artist-$song $song
mv $song ./$artist
done

到目前为止,最简单的方法是使用 rename a.k.a。 Perl rename.

基本上,你想用正斜杠目录分隔符替换序列 SPACE-DASH-SPACE,所以命令是:

rename --dry-run -p 's| - |/|' *mp3

示例输出

'Artist - Song name.mp3' would be renamed to 'Artist/Song name.mp3'
'Artist B - Song name 2.mp3' would be renamed to 'Artist B/Song name 2.mp3'

如果看起来正确,只需再次删除 --dry-run 和 运行 即可。使用 rename 的好处是:

  • 它可以在您 运行 之前进行干式 运行 测试
  • 它将使用 -p 选项创建所有必要的目录
  • 它不会在没有警告的情况下破坏(覆盖)文件
  • 您可以使用 Perl 的全部功能,并且可以根据需要进行复杂的重命名。

请注意,您可以在 macOS 上使用 homebrew 安装:

brew install rename

以防万一您没有 rename 实用程序。修复您的原始脚本。

for f in *.mp3; do
  # extract artist and song name and remove spaces
  artist=${f%% -*}
  song=${f##*- }
  #make directory with the extracted artist name and move + rename the file into the directory
  echo mkdir -p -- "$artist" && echo mv -- "$f" "$artist/$song"
done
  • 如果您对输出感到满意,请删除 echo