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

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

我基本上想从这里开始:

.
├── 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 做到这一点那就太好了,但我不知道如何做。

答案1

也许是这样的?

#!/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如果任何目录包含隐藏文件名或任何新目录创建失败,则调用将失败。

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

答案2

兹什

未经测试:

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}' */*/

答案3

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

从战术上讲,完成这项工作的模式如下:

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}depthGNU 和一些 BSD 支持find,但不支持 POSIX:在这种情况下,依赖*/*或类似的 shell 体操。

相关内容