如何在遍历bash脚本的文件夹中匹配多个文件名模式并批量重命名



我正在尝试自动化一项任务,到目前为止,我一直使用重命名实用程序手动执行该任务。不过,我对bash没有太多经验,所以我很难理解它的复杂性

我有未排序的漫画(.cbz文件(,可能采用以下命名风格(实际示例-我可能错过了一些(:

/Collection
├── /Title1
│   ├── _66.cbz
│   └── _Chapter 67.cbz
├── /Title2
│   ├── Chapter 117.cbz
│   └── Chapter 118 - Name.cbz
├── /Title3
│   ├── foo bar_Ch.10 - Name.cbz
│   ├── foo_Ch.21.cbz
│   └── foo_Ch.22.cbz
├── /Title4
│   ├── _Chapter 72_Voluminous.cbz
│   └── _Chapter 73_Final Chapter.cbz
├── /Title5
│   └── name.cbz
├── /Title6
│   └── Chapter 11 - Ch.11.cbz
└── /Title7
├── bar_Ch.58.2.cbz
└── bar_Vol.11 Ch.58.1.cbz

可以看出,结构完全混乱,未排序的文件夹之间没有一致性
我制定的一般规则集如下:
(可以随意更改以使其更好地工作(

  1. 如果.*Vol.匹配,则删除之前的所有内容,即用Vol.替换(可能还包括"Volume.2",但我不记得看到过(
  2. Elif.*Chapter匹配,替换为Ch.
  3. Elif.*Ch.替换为Ch.
  4. 如果只在章节编号(/Title1/_66.cbz(之前加上Ch.
  5. Else回波错误
  6. _替换为-(空格填充(

。。。对于目录中的每个*.cbz文件

这将产生以下输出:

/Collection
├── /Title1
│   ├── Ch.66.cbz
│   └── Ch.67.cbz
├── /Title2
│   ├── Ch.117.cbz
│   └── Ch.118 - Name.cbz
├── /Title3
│   ├── Ch.10 - Name.cbz
│   ├── Ch.21.cbz
│   └── Ch.22.cbz
├── /Title4
│   ├── Ch.72 - Voluminous.cbz
│   └── Ch.73 - Final Chapter.cbz
├── /Title5
│   └── name.cbz
├── /Title6
│   └── Ch.11.cbz
└── /Title7
├── Ch.58.2.cbz
└── Vol.11 Ch.58.1.cbz

到目前为止,我已经尝试了一些东西,但没有这么大的范围。请注意,有些章节名称可能包括Vol或Cha。

剩下的部分我可能自己就能解决。它们包括将脚本应用于/collection中每个/title的内容,这样我只需要从父目录运行一次。

可以制作一个直接匹配所需内容的正则表达式,但它很复杂,无法维护。从这个意义上说,你把问题分解成更小的部分是正确的。您不应该在循环tho中使用这么多sed调用;实际上,bash可以直接捕获数据,甚至根本不需要sed

以下解决方案具有一些缺点,例如;"体积";必须位于";章节";在文件名中,但它应该适用于您的目的:

#!/bin/bash
for file in 
Ch.33/_66.cbz '_Chapter 67.cbz' 'Chapter 117.cbz' 'Chapter 118 - Name.cbz' 
'foo bar_Ch.10 - Name.cbz' foo_Ch.21.cbz foo_Ch.22.cbz '_Chapter 72_Voluminous.cbz' 
'_Chapter 73_Final Chapter.cbz' bar_Ch.58.2.cbz 'bar_Vol.11 Ch.58.1.cbz'
do
[[ $file =~ ^(.*/)?(.*)(..*)$ ]]
dirname=${BASH_REMATCH[1]}
filename=${BASH_REMATCH[2]}
extension=${BASH_REMATCH[3]}
[[ $filename =~ Vol(ume)?[. ]([0-9]+) ]]
volume=${BASH_REMATCH[2]}
filename=${filename#*"${BASH_REMATCH[0]}"}
[[ $filename =~ Ch(apter)?[. ]([0-9]+(.[0-9]+)*)|([0-9]+(.[0-9]+)*) ]]
chapter=${BASH_REMATCH[2]}${BASH_REMATCH[4]}
[[ ${chapter:+X} ]] || {
printf 'illegal filename: %qn' "$file" 1>&2
continue
}
filename=${filename#*"${BASH_REMATCH[0]}"}
[[ $filename =~ [_ ]+(- +)?(.*)$ ]]
title=${BASH_REMATCH[2]}
filename=${volume:+Vol."$volume" }Ch.$chapter${title:+ - "$title"}
printf '%q %q %qn' mv "$file" "$dirname$filename$extension"
done
mv Ch.33/_66.cbz Ch.33/Ch.66.cbz
mv _Chapter 67.cbz Ch.67.cbz
mv Chapter 117.cbz Ch.117.cbz
mv Chapter 118 - Name.cbz Ch.118 - Name.cbz
mv foo bar_Ch.10 - Name.cbz Ch.10 - Name.cbz
mv foo_Ch.21.cbz Ch.21 - Name.cbz
mv foo_Ch.22.cbz Ch.22 - Name.cbz
mv _Chapter 72_Voluminous.cbz Ch.72 - Voluminous.cbz
mv _Chapter 73_Final Chapter.cbz Ch.73 - Final Chapter.cbz
mv bar_Ch.58.2.cbz Ch.58.2 - Final Chapter.cbz
mv bar_Vol.11 Ch.58.1.cbz Vol.11 Ch.58.1 - Final Chapter.cbz

试试这个:

find /Collection -name "*.cbz" | while read file; do
dir=$(dirname $file)
fileName=$(basename $file)
case "$fileName" in 
*Vol*)
newFileName=$(echo $fileName | sed -E 's/[^0-9]+([0-9]{2,3})/Vol.1/;s/_/ - /')            
;;
*)
newFileName=$(echo $fileName | sed -E 's/[^0-9]+([0-9]{2,3})/Ch.1/;s/_/ - /')
;;
esac
mv $file $dir/$newFileName
done

find搜索Collection文件夹中每个扩展名为cbz的文件的情况下;Vol";字符串和另一个字符串。

正则表达式:

  • [^0-9]+搜索任何不在0-9范围内的字符
  • ([0-9]{2,3})后跟2或3个数字

您可以使用这个在线sed来提供帮助。

最新更新