Linux:将文件从具有相同名称的不同目录移动到一个目录中,同时重命名它们

Linux:将文件从具有相同名称的不同目录移动到一个目录中,同时重命名它们

我将旧 CD 批量翻录为 Track1.mp3。问题是每个 CD 目录都有 Track1.mp3,所以当我将它们移动到 /Music 时,它们会被覆盖!

是否有可能有一个 bash 脚本或 mv 命令来移动是否将多个子目录中具有相同文件名的 .mp3 复制到一个目录中,如果该名称在 LINUX 下已经存在,则重命名它们?

答案1

您很可能想要“友好”的重命名。假设您有一个如下的

Artist1-+
        +-AlbumA-+
        |        +-Track1.mp3
        |        +-Track2.mp3
        +-AlbumB-+
                 +-Track1.mp3
                 +-Track2.mp3
Artist2-+
        +-AlbumX-+
        |        +-Track1.mp3
        |        +-Track2.mp3
        +-AlbumY-+
        |        +-Track1.mp3
        |        +-Track2.mp3

您现在希望单个目录包含类似以下内容的内容

Artist1-AlbumA-Track1.mp3
Artist1-AlbumA-Track2.mp3
...
Artist2-AlbumY-Track1.mp3
Artist2-AlbumY-Track2.mp3

bash这可以通过一个简单的循环来实现

for M in */*/*.mp3; do
  TRACK=$(basename "$M")
  ALBUM=$(basename $(dirname "$M"))
  ARTIST=$(basename $(dirname $(dirname "$M")))
  mv "$M" "$TARGET_DIR/$ARTIST-$ALBUM-$TRACK"
done

答案2

cp和命令mv通过选项支持此功能--backup

来自手动的

   --backup[=CONTROL]
          make a backup of each existing destination file

   -b     like --backup but does not accept an argument

[...]

备份后缀为“~”,除非使用 --suffix 或 SIMPLE_BACKUP_SUFFIX 设置。版本控制方法可以通过 --backup 选项或 VERSION_CONTROL 环境变量选择。以下是值:

   none, off
          never make backups (even if --backup is given)

   numbered, t
          make numbered backups

   existing, nil
          numbered if numbered backups exist, simple otherwise

   simple, never
          always make simple backups

因此例如应该mv --backup=t <source_file> <dest_file>可以工作。

答案3

据 Linux 社区和 commandlinefu.com 称,迄今为止,任何版本都无法实现这一便捷功能。

目前没有命令,也没有通过命令行的可靠方法将文件从具有相同名称的多个目录和子目录移动到单个目录中,而不覆盖它们。

资料来源:commandlinefu.com、askubuntu.com、linuxquestions.org、superuser.com

答案4

我假设你有一个这样的文件夹结构:

$ tree .
.
├── artist1
│   ├── albuma
│   │   └── Track1.mp3
│   └── albumb
│       └── Track1.mp3
└── artist two
    ├── album one
    │   └── Track1.mp3
    └── album two
        └── Track1.mp3

首先,cd到您的 MP3 收藏的父文件夹(的父文件夹artist1)。

现在,如果您运行以下find命令,您将看到如下输出:

$ find . -name '*.mp3' -exec bash -c 'echo mv -v "$1" /tmp/music/$(echo "$1" | sed "s/\.\///" | tr " /" "-")' bash {} \;
mv -v ./artist two/album one/Track1.mp3 /tmp/music/artist-two-album-one-Track1.mp3
mv -v ./artist two/album two/Track1.mp3 /tmp/music/artist-two-album-two-Track1.mp3
mv -v ./artist1/albuma/Track1.mp3 /tmp/music/artist1-albuma-Track1.mp3
mv -v ./artist1/albumb/Track1.mp3 /tmp/music/artist1-albumb-Track1.mp3
  • find收集 MP3 文件的所有路径,例如,./artist two/album one/Track1.mp3并将它们传递给bashvia-exec
  • $(echo "$1" | sed "s/\.\///" | tr " /" "-")用于修改输出文件名。sed删除第一个./并将tr所有空格字符和转换/-

必须以作为起始目录运行find.否则(相对)输出路径将无法正确修改。更改/tmp/music/为音乐库的路径。

如果输出看起来不错,则删除第一个echo并再次执行该命令。

输出:

$ find . -name '*.mp3' -exec bash -c 'mv -v "$1" /tmp/music/$(echo "$1" | sed "s/\.\///" | tr " /" "-")' babbsh {} \;
'./artist two/album one/Track1.mp3' -> '/tmp/music/artist-two-album-one-Track1.mp3'
'./artist two/album two/Track1.mp3' -> '/tmp/music/artist-two-album-two-Track1.mp3'
'./artist1/albuma/Track1.mp3' -> '/tmp/music/artist1-albuma-Track1.mp3'
'./artist1/albumb/Track1.mp3' -> '/tmp/music/artist1-albumb-Track1.mp3'

相关内容