移动并重命名剧集文件脚本


目录
  1. 1. mr-videos.sh
  2. 2. 使用效果
  3. 3. 修正2025.7.25

下载剧集经常是一集在一个目录里,整理的时候要移动到根目录并按集数重命令,手动操作比较繁琐。让deepseek给写了一个脚本来完成这个任务。

mr-videos.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/bin/bash

# 获取当前目录名
current_dir=$(basename "$PWD")

# 支持的视频文件扩展名数组
video_extensions=("mp4" "mkv" "avi" "mov" "flv" "wmv" "webm" "mpeg" "mpg" "3gp" "m4v")

# 临时存储提取的集数和对应文件名的数组
declare -A episode_map
declare -a files_without_episode
declare -a renamed_files
declare -a skipped_files

# 首先收集所有视频文件并尝试提取集数
while IFS= read -r -d '' file; do
# 获取文件扩展名(小写)
extension=$(echo "${file##*.}" | tr '[:upper:]' '[:lower:]')

# 检查是否是视频文件
if [[ " ${video_extensions[@]} " =~ " ${extension} " ]]; then
# 尝试从文件名中提取集数(改进正则表达式)
episode_num=$(echo "$file" | grep -o -E '第[0-9一二三四五六七八九十百]+集|集数[0-9]+|EP[0-9]+|Episode[[:space:]]*[0-9]+|S[0-9]+E[0-9]+|[0-9]{1,4}' | grep -o -E '[0-9]+' | head -1)

if [[ -n "$episode_num" ]]; then
# 如果找到集数,记录到映射表中(去掉前导零)
episode_map["$(echo $episode_num | sed 's/^0*//')"]="$file"
else
# 否则加入未找到集数列表
files_without_episode+=("$file")
echo "未找到集数信息: $file"
fi
fi
done < <(find . -type f -print0)

# 处理有集数信息的文件
for episode in "${!episode_map[@]}"; do
file="${episode_map[$episode]}"
extension="${file##*.}"

# 格式化集数(两位数,去掉前导零问题)
formatted_episode=$(printf "%02d" $((10#$episode)))
new_name="${current_dir}${formatted_episode}.${extension}"

# 检查是否已存在同名文件
if [[ -f "$new_name" ]]; then
echo "文件已存在,跳过: $file (目标文件 $new_name 已存在)"
skipped_files+=("$file")
continue
fi

# 移动文件
echo "移动并重命名(集数提取): $file -> $new_name"
mv "$file" "$new_name"
renamed_files+=("$new_name")
done

# 输出总结信息
echo ""
echo "操作完成。"
echo "成功重命名 ${#renamed_files[@]} 个文件:"
for file in "${renamed_files[@]}"; do
echo " $file"
done

echo ""
if [[ ${#skipped_files[@]} -gt 0 ]]; then
echo "以下 ${#skipped_files[@]} 个文件因目标文件已存在而被跳过:"
for file in "${skipped_files[@]}"; do
echo " $file"
done
echo ""
fi

if [[ ${#files_without_episode[@]} -gt 0 ]]; then
echo "以下 ${#files_without_episode[@]} 个文件未找到集数信息,未进行重命名:"
for file in "${files_without_episode[@]}"; do
echo " $file"
done
echo ""
fi

# 删除所有空子目录
echo "正在删除空子目录..."
find . -mindepth 1 -type d -empty -delete
echo "空子目录删除完成。"
  • 遇到已存在的目标文件时会跳过而不是覆盖
  • 显示所有操作结果的详细分类信息
  • 删除空子目录的功能

使用效果



基本上可以完成任务。

修正2025.7.25

如果子目录名和文件名重名则移动文件失败,需要先重命名文件夹,去掉象.mp4,.mkv之类的后缀,再进行文件移动和重命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/bin/bash

# 支持的视频文件扩展名数组
video_extensions=("mp4" "mkv" "avi" "mov" "flv" "wmv" "webm" "mpeg" "mpg" "3gp" "m4v")

# 第一步:清理所有子目录名中的视频后缀
echo "正在清理子目录名中的视频后缀..."
find . -mindepth 1 -type d | while read -r dir; do
original_dir="$dir"
# 去掉目录名中的视频后缀
clean_dir=$(echo "$dir" | sed -E 's/\.(mp4|mkv|avi|mov|flv|wmv|webm|mpeg|mpg|3gp|m4v)$//i')

if [[ "$original_dir" != "$clean_dir" ]]; then
echo "重命名目录: $original_dir -> $clean_dir"
mv "$original_dir" "$clean_dir"
fi
done
echo "子目录名清理完成。"

# 获取当前目录名(去掉可能的后缀)
current_dir=$(basename "$PWD" | sed -E 's/\.(mp4|mkv|avi|mov|flv|wmv|webm|mpeg|mpg|3gp|m4v)$//i')

# 第二步:处理视频文件
declare -A episode_map
declare -a files_without_episode
declare -a renamed_files
declare -a skipped_files

echo "开始处理视频文件..."
while IFS= read -r -d '' file; do
# 获取文件扩展名(小写)
extension=$(echo "${file##*.}" | tr '[:upper:]' '[:lower:]')

# 检查是否是视频文件
if [[ " ${video_extensions[@]} " =~ " ${extension} " ]]; then
# 尝试从文件名中提取集数
episode_num=$(echo "$file" | grep -o -E '第[0-9一二三四五六七八九十百]+集|集数[0-9]+|EP[0-9]+|Episode[[:space:]]*[0-9]+|S[0-9]+E[0-9]+|[0-9]{1,4}' | grep -o -E '[0-9]+' | head -1)

if [[ -n "$episode_num" ]]; then
# 如果找到集数,记录到映射表中(去掉前导零)
episode_map["$(echo $episode_num | sed 's/^0*//')"]="$file"
else
# 否则加入未找到集数列表
files_without_episode+=("$file")
echo "未找到集数信息: $file"
fi
fi
done < <(find . -type f -print0)

# 处理有集数信息的文件
for episode in "${!episode_map[@]}"; do
file="${episode_map[$episode]}"
extension="${file##*.}"

# 格式化集数(两位数,解决前导零问题)
formatted_episode=$(printf "%02d" $((10#$episode)))
new_name="${current_dir}${formatted_episode}.${extension}"

# 检查是否已存在同名文件
if [[ -f "$new_name" ]]; then
echo "文件已存在,跳过: $file (目标文件 $new_name 已存在)"
skipped_files+=("$file")
continue
fi

# 移动文件
echo "移动并重命名(集数提取): $file -> $new_name"
mv "$file" "$new_name"
renamed_files+=("$new_name")
done

# 输出总结信息
echo ""
echo "操作完成。"
echo "成功重命名 ${#renamed_files[@]} 个文件:"
for file in "${renamed_files[@]}"; do
echo " $file"
done

echo ""
if [[ ${#skipped_files[@]} -gt 0 ]]; then
echo "以下 ${#skipped_files[@]} 个文件因目标文件已存在而被跳过:"
for file in "${skipped_files[@]}"; do
echo " $file"
done
echo ""
fi

if [[ ${#files_without_episode[@]} -gt 0 ]]; then
echo "以下 ${#files_without_episode[@]} 个文件未找到集数信息,未进行重命名:"
for file in "${files_without_episode[@]}"; do
echo " $file"
done
echo ""
fi

# 第三步:删除所有空子目录(确保不删除名称像视频文件的目录)
echo "正在删除空子目录..."
find . -mindepth 1 -type d -empty -not -regex '.*\.(mp4|mkv|avi|mov|flv|wmv|webm|mpeg|mpg|3gp|m4v)$' -delete
echo "空子目录删除完成。"

写一个健壮的脚本真的很难。

Top, Home