我基本上想从这里开始:
.
├── 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
定位所有目录距当前工作目录正好两层,当前工作目录应该是包含乐队的目录:因此两层深是乐队名称下面的专辑名称。1xargs
消耗包含专辑的每个路径并调用内联 bash 脚本。bash -c '...'
将专辑路径作为其第一个参数,将该路径分为两部分:乐队 ($b
) 和专辑 ($a
)。最后,脚本将名称重新组合成所需的格式,并将新目录名称链接到原始目录。
请注意,在本例中,链接将在您开始的同一目录中创建,该目录也恰好是乐队名称所在的位置。
您可以而且应该调整ln
上述策略以符合您的意图。mv
如果您想要重新排列,或者ln
想要在媒体上创建方便的“视图”,请使用正确的路径。 bash 脚本中的重要部分是:
$b
乐队名称。始终引用它:"$b"
。$a
专辑名称。始终引用它:"$a"
。$1
专辑目录的物理路径。始终引用它:"$1"
。
1我相信m{ax,in}depth
GNU 和一些 BSD 支持find
,但不支持 POSIX:在这种情况下,依赖*/*
或类似的 shell 体操。