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

• 9 分钟阅读 • linux · deepseek

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

mr-videos.sh

#!/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之类的后缀,再进行文件移动和重命名。

#!/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 "空子目录删除完成。"

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

文章标签: linux, deepseek

上一篇 : docker里的中文dos游戏
下一篇 : ssh免密登录设置
留言
阅读进度 0%