因为涉及文件重名处理逻辑(如果有重名,带上前缀;如果没有重名,保持原样),脚本需要分两步走:

  1. 第一步:扫描一遍,统计哪些文件名重复了。
  2. 第二步:执行复制和重命名。如果是重复的文件,就加上父目录名作为前缀。

这是一个完整的 Bash 脚本,你可以直接复制并在 Linux 终端中运行。

脚本代码 (collect_code.sh)

#!/bin/bash

# ================= 配置区域 =================
# 默认的源目录(如果没有输入参数,使用这个路径,或者报错)
# 这里设置为脚本接收的第一个参数
SOURCE_DIR="$1"

# 目标存放的根目录
TARGET_BASE_DIR="/home/woankeji/Documents"
# 新建的文件夹名称 (自动加上时间戳,防止覆盖之前的)
NEW_FOLDER_NAME="flattened_code_$(date +%Y%m%d_%H%M%S)"
DEST_DIR="$TARGET_BASE_DIR/$NEW_FOLDER_NAME"

# ================= 检查输入 =================
if [ -z "$SOURCE_DIR" ]; then
    echo "❌ 错误: 请输入源目录路径。"
    echo "用法: ./collect_code.sh <你的源代码目录>"
    echo "示例: ./collect_code.sh ~/Desktop/osc-kvs-6262l/projects/wlab/osc/source"
    exit 1
fi

if [ ! -d "$SOURCE_DIR" ]; then
    echo "❌ 错误: 目录 '$SOURCE_DIR' 不存在。"
    exit 1
fi

# ================= 准备工作 =================
echo "📂 源目录: $SOURCE_DIR"
echo "📂 目标目录: $DEST_DIR"

# 创建目标文件夹
mkdir -p "$DEST_DIR"
if [ $? -ne 0 ]; then
    echo "❌ 无法创建目标目录,请检查权限。"
    exit 1
fi

echo "🔍 正在扫描文件并计算文件名重复情况..."

# 定义一个关联数组来存储文件名出现的次数
declare -A file_counts

# 1. 第一遍扫描:统计文件名出现的次数
# 使用 find 查找所有 .c 和 .h 文件
while IFS= read -r file; do
    filename=$(basename "$file")
    # 计数加1
    ((file_counts["$filename"]++))
done < <(find "$SOURCE_DIR" -type f \( -name "*.c" -o -name "*.h" \))

echo "🚀 开始复制并重命名文件..."

# 2. 第二遍扫描:复制并重命名
count=0
while IFS= read -r file; do
    filename=$(basename "$file")
    
    # 获取该文件名在整个项目中出现的总次数
    occurrence=${file_counts["$filename"]}
    
    # 确定新文件名
    if [ "$occurrence" -gt 1 ]; then
        # === 冲突处理逻辑 ===
        # 如果文件名有重复,获取它的直接父目录名称
        parent_dir_path=$(dirname "$file")
        parent_dir_name=$(basename "$parent_dir_path")
        
        # 组合新名字: 父目录_文件名.txt
        # 例如: common/utils.c -> common_utils.c.txt
        new_filename="${parent_dir_name}_${filename}.txt"
        
        # 极端的边缘情况:如果不同路径下父目录名也一样 (例如 a/common/utils.c 和 b/common/utils.c)
        # 检查目标是否已经存在该文件,如果存在,再拼上一层目录或随机数
        if [ -f "$DEST_DIR/$new_filename" ]; then
             grandparent_name=$(basename "$(dirname "$parent_dir_path")")
             new_filename="${grandparent_name}_${parent_dir_name}_${filename}.txt"
        fi
    else
        # === 无冲突逻辑 ===
        # 没有重名,直接加 .txt 后缀
        new_filename="${filename}.txt"
    fi

    # 执行复制
    cp "$file" "$DEST_DIR/$new_filename"
    ((count++))
    
    # 打印进度 (可选)
    # echo "复制: $filename -> $new_filename"

done < <(find "$SOURCE_DIR" -type f \( -name "*.c" -o -name "*.h" \))

echo "------------------------------------------------"
echo "✅ 完成!"
echo "📊 共处理文件: $count 个"
echo "📂 所有文件已保存在: $DEST_DIR"
echo "   (你可以使用 'nautilus $DEST_DIR' 打开查看)"

如何使用这个脚本

  1. 保存脚本
    在你的终端中,创建一个文件,例如 collect_code.sh

    nano collect_code.sh
    

    把上面的代码粘贴进去,然后按 Ctrl+O 保存,Ctrl+X 退出。

  2. 赋予执行权限

    chmod +x collect_code.sh
    
  3. 运行脚本
    将你的源码目录作为参数传进去:

    ./collect_code.sh ~/Desktop/osc-kvs-6262l/projects/wlab/osc/source
    

脚本逻辑解析 (针对你的需求)

  1. 不改变原目录:脚本只执行 cp (复制) 操作,原目录下的任何文件都不会被修改。
  2. 目标目录:它会在 /home/woankeji/Documents 下创建一个类似 flattened_code_20231204_170000 的新文件夹。
  3. 智能重命名逻辑
    • 脚本使用了 declare -A file_counts (关联数组) 先把所有 .c.h 文件的名字统计了一遍。
    • 情况 A (无重名):比如 wlab_at.c 在整个目录里只出现了一次。
      • 结果:wlab_at.c.txt
    • 情况 B (有重名):比如 common/utils.cwifi/utils.c,统计发现 utils.c 出现了 2 次。
      • 脚本会自动提取父目录名 (commonwifi)。
      • 结果:common_utils.c.txtwifi_utils.c.txt
  4. 递归查找:使用 find 命令自动深入所有子文件夹(如 application/at, peripheral/adc 等)。

预期输出效果

执行后,/home/woankeji/Documents/flattened_code_.../ 文件夹内将包含:

  • wlab_at.c.txt
  • wlab_at.h.txt
  • power_control.c.txt
  • common_utils.c.txt (假设存在重名)
  • wifi_utils.c.txt (假设存在重名)
  • apt32.c.txt
  • … 等等,全部在一个平面目录下。

更多推荐