展平目录层次结构,在新目录名称中保留目录名称


7

我基本上想从这里开始:

.
├── Alan Walker
│   ├── Different World
│   │   ├── 01 Intro.mp3
│   │   ├── 02 Lost Control.mp3
│   │   └── cover.jpg
│   └── Same World
│       ├── 01 Intro.mp3
│       └── 02 Found Control.mp3
├── Aurora
│   └── Infections Of A Different Kind Step 1
│       ├── 01 Queendom.lrc
│       ├── 02 Forgotten Love.lrc
│       └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses
    └── Use Your Illusion I
        ├── 01 Right Next Door To Hell.lrc
        ├── 01 Right Next Door To Hell.mp3
        ├── 02 Dust N' Bones.lrc
        └── 02 Dust N' Bones.mp3

对此:

.
├── Alan Walker - Different World
│   ├── 01 Intro.mp3
│   ├── 02 Lost Control.mp3
│   └── cover.jpg
├── Alan Walker - Same World
│   ├── 01 Intro.mp3
│   └── 02 Found Control.mp3
├── Aurora - Infections Of A Different Kind Step 1
│   ├── 01 Queendom.lrc
│   ├── 02 Forgotten Love.lrc
│   └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses - Use Your Illusion I
    ├── 01 Right Next Door To Hell.lrc
    ├── 01 Right Next Door To Hell.mp3
    ├── 02 Dust N' Bones.lrc
    └── 02 Dust N' Bones.mp3

我找不到的现有解决方案中都没有包含重命名目录本身。能够使用zmv做到这一点真是太好了,但是我不知道该怎么做。


2
不是一个完整的解决方案,所以不是一个答案:easytag也许可以让您这样做,但只能用于音频文件-我认为它不会移动封面等
。– rvs

2
一个艺术家目录中的特定艺术家是否可以有多个专辑?结构始终是三个层次的深度吗?
nohillside

1
@nohillside是的,一个艺术家可以有多个专辑。是的,结构始终是三个层次。
aksh1618

Answers:


9

sh

未经测试:

zmv -Q '(*)/(*)(/)' '$1 - $2'
rmdir -- *(/^F)

第二行删除所有空目录,即使以前没有文件的目录也是如此。可以使用自定义mv包装程序解决此问题,该包装程序记录将内容从哪个目录移出。

请注意,这会遍历到当前目录中目录的符号链接。

Linux重命名实用程序

未经测试。

rename / ' - ' */*/
rmdir -- */ 2>/dev/null

请注意,这会遍历到当前目录及其子目录中目录的符号链接。第二行删除所有空目录,即使以前没有文件的目录也是如此。

Perl重命名脚本

未经测试。

prename 's~/~ - ~' */*/
rmdir -- */ 2>/dev/null

请注意,这会遍历到当前目录及其子目录中目录的符号链接。第二行删除所有空目录,即使以前没有文件的目录也是如此。

这是一种更复杂的方法,它仅删除从其重命名的目录。再次,未经测试。

prename 's~([^/]+)/~$1 - ~ and ++$d{$1}; END {map {rmdir} keys %d}' */*/

12

像这样的东西?

#!/bin/sh

for topdir in */; do
    topdir_name=$( basename "$topdir" )

    for subdir in "$topdir"/*/; do
        subdir_name=$( basename "$subdir" )

        newdir="$topdir_name - $subdir_name"
        if mkdir "$newdir"; then
            mv "$subdir"/* "$newdir"
            rmdir "$subdir"
        fi
    done

    rmdir "$topdir"
done

这会遍历当前目录中的所有顶级目录(乐队名称)。对于每个这样的目录,它将遍历其子目录(唱片集名称)。对于每对乐队名称和专辑名称,将创建一个新目录,并将子目录中的文件移至该目录。处理专辑子目录后,便会删除它们,原始的乐队顶级目录也是如此。

rmdir如有目录中包含隐藏文件名调用失败,或者如果任何新的目录无法生成。

这是完全未经测试的代码。在文件的备份副本上运行它。


我的意思是,是的,类似的方法会起作用,但是我有点在寻找一种或两种线路的解决方案,以便从终端轻松运行。一些查找/ sed / zmv魔术:)
aksh1618

10
将ot放入脚本中,然后-boom-变成单线。
汉斯·马丁·莫斯纳

4

从策略上讲,您是否考虑过保留当前结构并为所需的新结构创建链接,而不是移动文件?

从战术上讲,完成任务的模式如下:

find . -mindepth 2 -maxdepth 2 -type d -print0 | xargs -0n1 bash -c \
  'b=$(basename "$(dirname "$1")"); a=$(basename "$1"); echo ln -s "$1" "$b-$a"' {}
  • find在当前工作目录(应该是包含乐队)的目录的最下两层找到所有目录:因此,在乐队名称下方的唱片集名称最深两层。1个
  • xargs 使用包含专辑的每个路径,并调用内联bash脚本。
  • bash -c '...'将专辑路径作为其第一个参数,将该路径分为两部分:乐队($b)和专辑($a)。最后,脚本将名称重新组合为所需的格式,并将新目录名称链接到原始目录。

请注意,在此示例中,链接将在您开始时所在的目录中创建,该目录也恰好是乐队名称所在的目录。

您可以-并且应该-调整上述ln策略以符合您的意图。mv如果您实际要重新排列,或者ln要在媒体上创建方便的“视图” ,请使用正确的路径。bash脚本中的重要部分是:

  • $b乐队名称。始终引用:"$b"
  • $a专辑名称。始终引用:"$a"
  • $1相册目录的物理路径。始终引用:"$1"

1我相信m{ax,in}depth受到GNU和某些BSD的支持find,但不受POSIX的支持:在这种情况下,请依靠*/*或类似的贝壳体操。


1
我喜欢这个答案...您也可以建立硬链接,然后在满意时删除旧的文件夹结构
Thomas Zwaagstra

@ThomasZwaagstra与移动文件没有什么不同
Darkhogg

1
@Darkhogg就是这样!OP正在寻找一种可移动文件的衬板。在此解决方案中使用硬链接几乎可以完成此任务,除了在删除原始文件之前需要一个中间的“预览”阶段
Thomas Zwaagstra
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.