1.背景
组件化过程中,有一些重复/高频的问题需要解决,倘若手动解决会带来重复劳动的时间损失,以及没有沉淀的效率损失,为了避免上述损失,沉淀一些工具分享。
2.组件化工具介绍
2.1 Xcode编译错误解决工具
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
| #!/bin/bash
# [背景]
# 组件化过程中,经常出现以下编译错误:
# Build service could not create build operation: unknown error while handling message: MsgHandlingError(message: "unable to initiate PIF transfer session (operation in progress?)")
#
# author: PaysonChen
# [目的]
# 为解决上述错误,需要清理构建索引目录并重启xcode,由于操作重复,考虑抽出shell脚本
#
# [目录]
# - auto_clean.sh
# [说明]
# 1、CD[指定xcode构建索引目录]目录
# 2、递归删除当前文件下所有文件
# 3、重启xcode
#
# [参数]
# 1、参数1,指定xcode构建索引目录
# 1、参数2,指定要打开的Xcode项目目
#
# [调用说明]
# 1、未指定目录,则取当前目录:sh auto_clean.sh
# 2、指定目录:sh auto_clean.sh /xcode构建索引目录/ /要打开的Xcode项目目录/
#获取当前用户名
user_name=$(whoami)
export XcodeDerivedDataPath=/Users/$user_name/Library/Developer/Xcode/DerivedData
export XcodeWorkspacePath=/Applications/Xcode.app
if [ -z "$1" ]; then
echo '///入参1为空,使用默认xcode构建索引目录:'${XcodeDerivedDataPath}
else
XcodeDerivedDataPath=$1
echo '///入参1不为空,xcode构建索引目录:'${XcodeDerivedDataPath}
fi
if [ -z "$2" ]; then
echo '///入参2为空,使用默认xcode项目目录:'${XcodeWorkspacePath}
else
XcodeWorkspacePath=$2
echo '///入参2不为空,xcode项目目录:'${XcodeWorkspacePath}
fi
#cd到xcode构建索引目录
cd $XcodeDerivedDataPath
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo '///切换目录失败:'${XcodeDerivedDataPath}
exit -1
else
echo '///切换目录成功:'${XcodeDerivedDataPath}
fi
#删除当前目录所有构件索引
rm -rf *
#重启xcode
killall Xcode
#休眠一下,不然可能导致重启失败
sleep 0.1
#重启项目工程
open $XcodeWorkspacePath
|
2.2 私有组件批量更新工具
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
| #!/bin/bash
# 遍历更新当前目录下,子目录git仓库的脚本
# author: PaysonChen
# [目的]
# 组件化建设过程及后续的协同开发中,经常碰到团队人员更新组件库代码及主工程,主工程容易更新,但是随着pod库的增多,每次更新组件库仓库的重复劳动需要被改进
#
# [目录]
# - auto_update_git.sh.sh 遍历更新当前目录下,子目录git仓库的脚本
#
# [说明]
# 1、遍历指定目录(若未传参数则为当前目录)下的子目录
# 2、cd 到子目录
# 3、检查当前分支
# 4、拉取远端当前分支
#
# [参数]
# 1、参数1,指定目录
#
# [调用说明]
# 1、未指定目录,则取当前目录:sh auto_update_git.sh
# 2、指定目录:sh auto_update_git.sh /User/xxx/xx
if [ -z "$1" ]; then
export dist_path=*/
echo '///指定目录 为空:'${dist_path}
else
export dist_path=$1/*/
echo '///指定目录 不为空:'${dist_path}
fi
# 遍历指定目录的子目录
for dir in ${dist_path}; do
cd "$dir" # 进入子目录
echo '///进入子目录:'${dir}
# 检查是否是git仓库
if [ -d .git ]; then
echo "Updating git repository in $dir"
current_branch=`git branch --show-current`
echo "current_branch is $current_branch"
git config pull.rebase false # 合并(缺省策略)
git pull origin $current_branch # 使用git pull命令更新git仓库
else
echo "Skipping non-git repository in $dir"
fi
cd .. # 返回上一级目录
done
|
2.3 私有组件批量提交工具
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
| #!/bin/bash
# 遍历更新当前目录下,子目录git仓库的脚本
# author: PaysonChen
# [目的]
# 组件化建设过程及后续的协同开发中,经常碰到团队人员更新组件库代码及主工程,主工程容易更新,但是随着pod库的增多,每次更新组件库仓库的重复劳动需要被改进
#
# [目录]
# - auto_commit_git.sh 遍历更新当前目录下,子目录git仓库的脚本
#
# [说明]
# 1、遍历指定目录(若未传参数则为当前目录)下的子目录
# 2、cd 到子目录
# 3、检查当前分支
# 4、提交修改
# 5、commit 、push
#
# [参数]
# 1、参数1,指定目录
# 2、参数2,提交信息
#
# [调用说明]
# 1、未指定目录,则取当前目录:sh auto_commit_git.sh
# 2、指定目录:sh auto_commit_git.sh /User/xxx/xx "提交信息"
if [ -z "$1" ]; then
export dist_path=*/
echo '///指定目录 为空:'${dist_path}
else
export dist_path=$1/*/
echo '///指定目录 不为空:'${dist_path}
fi
echo '///指定:'$1
echo '///指定:'$2
# 遍历指定目录的子目录
for dir in ${dist_path}; do
cd "$dir" # 进入子目录
echo '///进入子目录:'${dir}
# 检查是否是git仓库
if [ -d .git ]; then
echo "commiting git repository in $dir"
current_branch=`git branch --show-current`
echo "current_branch is $current_branch"
git add .
msg=""
if [ -z "$2" ]; then
msg="--update:更新代码"
echo '///提交记录 为空:'$msg
else
msg=$2
echo '///提交记录 不为空:'$msg
fi
git commit -m "$msg"
git push -f origin master
else
echo "Skipping non-git repository in $dir"
fi
cd .. # 返回上一级目录
done
|
2.4 私有组件批量发版工具
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
| #!/bin/bash
# 遍历当前目录下,私有库自动自增发版
# author: PaysonChen
# [目的]
# 组件化建设过程及后续的协同开发中,有些全局修改需要统一发版
#
# [目录]
# - auto_publish_git.sh 遍历当前目录下,私有库自动自增发版
#
# [说明]
# 1、遍历指定目录(若未传参数则为当前目录)下的子目录
# 2、cd 到子目录
# 3、检查当前分支
# 4、自动发版
#
# [参数]
# 1、参数1,指定目录
#
# [调用说明]
# 1、未指定目录,则取当前目录:sh auto_publish_git.sh
# 2、指定目录:sh auto_publish_git.sh /User/xxx/xx
if [ -z "$1" ]; then
export dist_path=*/
echo '///指定目录 为空:'${dist_path}
else
export dist_path=$1/*/
echo '///指定目录 不为空:'${dist_path}
fi
# 遍历指定目录的子目录
for dir in ${dist_path}; do
cd "$dir" # 进入子目录
echo '///进入子目录:'${dir}
# 检查是否是git仓库
if [ -d .git ]; then
echo "Updating git repository in $dir"
current_branch=`git branch --show-current`
echo "current_branch is $current_branch"
if [ -z "$2" ]; then
echo "tag 为空,采用自增tag"
pod push
else
echo "tag 不为空,tag="$2
pod push $2
fi
else
echo "Skipping non-git repository in $dir"
fi
cd .. # 返回上一级目录
done
|
其中 pod push 依赖于cocapods插件(计划在后续文章中讲解)
2.5 私有组件批量发版工具-优化
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
| #!/bin/bash
# 遍历当前目录下,当最新提交不是Tag记录时(即有需要发版)才进行的私有库自动自增发版
# author: PaysonChen
# [目的]
# 组件化建设过程及后续的协同开发中,有些全局修改需要统一发版
#
# [目录]
# - auto_tag_if_need_git.sh 遍历当前目录下,私有库根据是否需要发版的逻辑进行自动自增发版
#
# [说明]
# 1、遍历指定目录(若未传参数则为当前目录)下的子目录
# 2、cd 到子目录
# 3、检查当前分支
# 4、自动发版
#
# [参数]
# 1、参数1,指定目录
#
# [调用说明]
# 1、未指定目录,则取当前目录:sh auto_tag_if_need_git.sh
# 2、指定目录:sh auto_tag_if_need_git.sh /User/xxx/xx
if [ -z "$1" ]; then
export dist_path=*/
echo '///指定目录 为空:'${dist_path}
else
export dist_path=$1/*/
echo '///指定目录 不为空:'${dist_path}
fi
function get_tag()
{
latest_tag=$(git describe --exact-match --tags $(git log -n1 --pretty='%h') 2>/dev/null)
echo "${latest_tag}"
}
function push_if_need()
{
if git describe --exact-match --tags $(git log -n1 --pretty='%h') >/dev/null 2>&1; then
latest_tag=$(get_tag)
echo "[push_if_need]:最新提交是一个标签(${latest_tag})$1。"
return 0
else
latest_tag=$(get_tag)
echo "[push_if_need]:最新提交不是标签(${latest_tag})$1。"
pod push
latest_tag=$(get_tag)
echo "[push_if_need]:打包后的标签(${latest_tag})$1。"
return 1
fi
}
# 遍历指定目录的子目录
allTaged=""
modifyTaged=""
for dir in ${dist_path}; do
cd "$dir" # 进入子目录
echo '///进入子目录:'${dir}
# 检查是否是git仓库
if [ -d .git ]; then
result=false
echo "Updating git repository in $dir"
current_branch=`git branch --show-current`
echo "current_branch is $current_branch"
git config pull.rebase false # 合并(缺省策略)
git pull origin $current_branch # 使用git pull命令更新git仓库
if [ -z "$2" ]; then
echo "tag 为空,采用自增tag"
# pod push
push_if_need $dir
result=$?
else
echo "tag 不为空,全量发版tag="$2
pod push $2
fi
latest_tag=$(get_tag)
pod_name=${dir%%/*}
allTaged="$allTaged pod \"$pod_name\",'$latest_tag' \n"
if [ $result -eq 1 ]; then
# latest_tag=$(get_tag)
# pod_name=${dir%%/*}
modifyTaged="$modifyTaged pod \"$pod_name\",'$latest_tag' \n"
# echo "变量是 true。"$dir
# echo "变量是 true。"$tmp
echo "变量是 true。"$modifyTaged
else
echo "变量是 false。"
fi
else
echo "Skipping non-git repository in $dir"
fi
cd .. # 返回上一级目录
done
echo "------------------------"
echo "allTaged(所有组件): = \n"$allTaged
echo "------------------------"
echo "------------------------"
echo "allTaged(本次有发版组件): = \n"$modifyTaged
echo "------------------------"
|
3.其他工具介绍
3.1 删除注释掉的#import工具
//#import "xxx.h"
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
| #!/bin/bash
# 遍历指定目录下的类删除注释掉的import代码行的脚本
# author: PaysonChen
# [目的]
# 工程阶段性整理无用import(注释掉)
#
# [目录]
# - delete_unused_import_annotation.sh
#
# [说明]
# 1、遍历指定目录
# 2、检索代码行
# 3、符合给定条件://import
# 4、删除代码行
#
# [参数]
# 1、参数1,指定目录
#
# [调用说明]
# 1 调用示例:sh delete_unused_import_annotation.sh your_path
find $1 -type f \( -name "*.h" -o -name "*.m" \) -exec sed -i '' '/\/\/#import/d' {} \;
|
3.2 未被引用的类文件清理工具
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
| #!/bin/bash
# [背景]
# 基础组件拆分到一定程度时,主工程剩下的就多数与视图界面(vc、view等)相关的类文件。此时可以考虑对业务组件进行设计和规划,但是在此时,工程还存在如下问题:
# 冗余文件:
# 未被引用到Project,但存在在工程目录中的冗余的类文件
#
# author: PaysonChen
# [目的]
# 为了减轻业务组件的工作量和复杂度,在此之前最好能净化/清理一下工程
#
# [目录]
# - find_all_file_no_project.sh
# [说明]
# 1、通过递归遍历工程目录,将遍历后的类名逐一与XXX.xcodeproj/project.pbxproj 文件内容进行匹配
# 2、匹配不成功则输出文件列表
# 3、【人工】对文件列表一一检查,确认是冗余文件则从工程中删除
#
# [参数]
# 1、参数1,指定xcode工程自身的主工程类所在目录,而非project所在的目录
# 例如 XXX/ProjectName/ProjectName.xcodeproj/project.pbxproj
# XXX/ProjectName/ProjectName/AppDelegate.h
# 需要传入的是下面这地址:
# XXX/ProjectName/ProjectName
# [调用说明]
# 1、未指定目录,则取当前目录:sh find_all_file_no_project.sh
# 2、指定目录:sh find_all_file_no_project.sh /Users/xxxxx/Project-IOS/ProjectName/ProjectName
#!/bin/bash
function main() {
# 设置项目目录
project_directory=$1
if [ -z "$1" ]; then
#未传参为当前目录
project_directory=.
fi
# 设置其他目录
parent_path=$(dirname "$project_directory")
echo "project 路径:"$parent_path
current_dir=$(basename "$project_directory")
echo "当前路径 文件夹名称:"$current_dir
project_path=$(find "$parent_path"/$current_dir.xcodeproj -type f \( -name "*.pbxproj" \))
echo "project 路径:"$project_path
all_file_path=$(find "$project_directory" -type f \( -name "*.h" \))
all_file_path_cnt=$(find "$project_directory" -type f \( -name "*.h" \) | wc -l)
echo "主工程 头文件数量:"$all_file_path_cnt
for src_file in $all_file_path; do
# echo $src_file
filename=$(basename "$src_file" .h)
if ! grep -q "\b$filename\b" "$project_path"; then
echo "project不包含:"$src_file
fi
done
}
main $1
|
3.3 未被使用的类文件清理工具
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
| #!/bin/bash
# [背景]
# 基础组件拆分到一定程度时,主工程剩下的就多数与视图界面(vc、view等)相关的类文件。此时可以考虑对业务组件进行设计和规划,但是在此时,工程还存在如下问题:
# 冗余文件:
# 非冗余但未被使用的文件
#
# author: PaysonChen
#
# [目的]
# 此脚本解决 "非冗余但未被使用的文件" 的清理
#
# [目录]
# - find_unused_class.sh
# [说明]
# 1 遍历工程目录的所有实现类:.m文件(不包含category)
# 2 将类名与工程内除自身以外所有文件进行进逐行匹配(包含category)
# 3 当匹配到不包含// 与 #import 开头的行,则算为有引用,否则为未引用
# 4 将未匹配到的文件路径进行输出
# 5 将上述匹配出来的文件先进行移除,再执行一遍(由于第一层被移除,可能会暴露出更多没被引用的类)
# 6 直到没有匹配到未被调用的类为止
#
# [参数]
# 1、参数1,指定xcode工程目录 (未指定则为当前目录)
#
# [调用说明]
# 1、未指定目录,则取当前目录:sh find_unused_class.sh
# 2、指定目录 :sh find_unused_class.sh /Users/xxxxx/ProjectName-IOS/ProjectName/ProjectName
#!/bin/bash
#是否重复执行到没有找到不可用文件
export cycle_deal=1
export cycle_idx=1
total_unused_file_name=''
function main() {
# 设置项目目录
project_directory=$1
if [ -z "$1" ]; then
#未传参为当前目录
project_directory=.
fi
#初始化参数:
unused_files=''
# 查找所有以ViewController.m结尾的文件并输出列表
all_class_path=$(find "$project_directory" -type f \( -name "*.m" \) | grep -v '+')
all_file_path=$(find "$project_directory" -type f \( -name "*.m" -o -name "*.h" \) )
file_cnt=0
for file in $all_class_path; do
file_cnt=$((file_cnt+1))
done
echo "*******file_cnt:"$file_cnt
for file in $all_class_path; do
filename=$(basename "$file" .m)
echo "***********开始遍历文件名:"$filename
is_referenced=false
for other_file in $all_file_path; do
other_file_name=$(basename "$other_file")
#获取除自身以外的类名:不包含拓展的名称,为了避免在自身的.h .m进行引用判断
other_file_name_without_extension=$(echo "$other_file_name" | cut -d. -f1)
#获取category的主类名称
other_file_name_without_extension_before_plus=$(echo "$other_file_name_without_extension" | awk -F'+' '{print $1}')
if [ "$other_file_name_without_extension_before_plus" != "$filename" ] ; then
# if [ "$other_file" != "$file" ] && ([ "${other_file##*.}" = "m" ] ); then
if grep -q "\b$filename\b" "$other_file"; then
# 检查文件中是否有注释行
has_comment=false
while IFS= read -r line; do
echo "逐行匹配:"$line
if ! grep -qE "^[[:space:]]*//" <<< "$line"; then
if [[ ! $line =~ ^[[:space:]]*#import ]]; then
has_comment=true
echo "在文件:"$other_file"匹配"$filename"存在 并且不是 注释代码 或者 import 的 break("$line
break
fi
fi
done <<< "$(grep "\b$filename\b" "$other_file")"
if [ "$has_comment" = true ]; then
is_referenced=true
break
fi
fi
fi
done
if [ "$is_referenced" = false ]; then
echo "没有被引用到的文件:"$file
unused_files="$unused_files$file\n"
fi
echo "***********"
done
# 输出未被引用的文件列表
if [ -n "$unused_files" ]; then
echo -e "Unused class files:\n$unused_files"
total_unused_file_name="$total_unused_file_name$unused_files\n"
#将检索出来的文件 mv 出来
mkdir -p ./unused_files/$cycle_idx/
array=(`echo $unused_files | tr '\n' ' '`)
for element in "${array[@]}"; do
element=$(echo "$element" | tr -d '\n')
echo "Unused class = "$element
element_filename=$(basename "$element" .m)
element_dirname=$(dirname "$element")
destFoldName="./unused_files/$cycle_idx/${element_dirname}/${element_filename}"
mkdir -p $destFoldName
cp -f ${element_dirname}/${element_filename}.h $destFoldName/$element_filename.h
cp -f ${element_dirname}/${element_filename}.m $destFoldName/$element_filename.m
done
#cycle_deal参数为空则不循环执行
if [ -z "$cycle_deal" ]; then
echo "cycle_deal参数为空则不循环执行"
exit 0
else
#cycle_deal 不为空 循环执行,直到不再有新文件检出
echo -e "循环执行"
cycle_idx=$((cycle_idx+1))
main $1
fi
else
echo "No unused ViewController files found."$all_file_path
echo "**************************"
echo "total_unused_file_name class files:\n$total_unused_file_name"
echo "**************************"
exit 0
fi
}
main $1
|
3.4 冲突解决工具
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
| #!/bin/bash
# [背景]
# 组件化过程中不可避免的会遇到这样一个问题:
# 组件化的过程一般周期比较长,此过程中不免会有业务需求的输入,这样就会导致一个情况:
# 组件化分支已经将主工程里的类迁移到pod仓库,而在此期间的业务需求代码对这些被迁移的类有修改,
# 合并主干(其他分支)代码时,主干(其他分支)有对移动之前的类做修改的情况下,会导致合并冲突,
# 这种冲突是整个类都是新增符号(+),没有冲突符号,此时无法简单的通过工具,或者冲突的符号对其进行解冲突。
#
# author: PaysonChen
# [目的]
# 为了减轻组件化分支合并主干分支的工作量和复杂度
#
# [目录]
# - merge.sh
# [说明]
# 1、整理project 冲突文件的路径列表
# 2、整理冲突列表在各个pod库中的路径列表
# 3、在未预合并分支上先mv一份整理后的pod库中的路径列表到主工程
# 4、再进行分支合并
# 5、解决冲突后,执行将主工程的上述列表,mv到各个pod库
# 6、提交各个Pod库代码
# 7、整理Project文件及工程类
# 8、提交Project代码
#
# [参数]
# 1、参数1:源路径:从参数1下的文件路径了列表,移动到参数2(索引)对应的路径
# 例如 merge_pods_files.txt
# 2、参数2,目标移动路径列表
# 例如 merge_project_files.txt
#
# [调用说明]
# 1、需要指定目录
# 从Pod移动到主工程:sh merge.sh merge_pods_files.txt merge_project_files.txt
# 从主工程移动到Pod:sh merge.sh merge_project_files.txt merge_pods_files.txt
# 从外部文件中读取源文件路径和目标文件夹路径
#"source_paths.txt"
source_file=$1
#"destination_paths.txt"
destination_file=$2
# 检查源文件是否存在
if [ ! -f "$source_file" ]; then
echo "源文件 '$source_file' 不存在。"
exit 1
fi
# 检查目标文件夹文件是否存在
if [ ! -f "$destination_file" ]; then
echo "源文件 '$source_file' 不存在。"
exit 1
fi
#保证每条记录都有一个回车(最后一行如果没有回车,会被忽略)
while IFS= read -r source_path && IFS= read -r destination_folder <&3; do
source_paths+=("$source_path")
destination_paths+=("$destination_folder")
done < $source_file 3< $destination_file
# 输出数组长度
echo "源文件路径数组长度:${#source_paths[@]}"
echo "目标文件夹路径数组长度:${#destination_paths[@]}"
#exit 0
# 遍历索引
for index in "${!source_paths[@]}"; do
echo "遍历目标文件夹路径数组,index="$index
source_path="${source_paths[$index]}"
destination_path="${destination_paths[$index]}"
# 构建目标文件的完整路径
# destination_path="${destination_folder}${source_path}"
# 检查目标文件是否存在,如果存在则删除
if [ -e "$destination_path" ]; then
rm "$destination_path"
fi
# 确保目标文件夹存在
mkdir -p "$(dirname "$destination_path")"
# 复制源文件到目标路径
mv "$source_path" "$destination_path"
done
echo "文件复制完成。"
|
3.5 版权信息批量同步工具
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
| #!/bin/bash
# 遍历更新当前目录下(含子目录)所有iOS工程类文件:.h .m .swift 并对其注释头进行模板替换
# author: PaysonChen
# [目的]
#
# 组件化规整之后,可能存在的情况是前后的文件命名不一致导致的影响代码易读性、易维护等问题
# 除此之外,由于代码经由不同人迭代的,甚至不同组织迭代(从外包接手的项目)还存在一些文件注释的注释模板差异的情况
# 此脚本目的为了解决存量类文件头注释统一性问题
#
# [目录]
# - replace_class_header_anotation.sh 遍历更新当前目录下,子目录git仓库的脚本
#
# [说明]
# 1、遍历指定目录(若未传参数则为当前目录)下的子目录
# 2、匹配所有iOS工程类文件:.h .m .swift
# 3、对其注释头进行模板替换
#
# [参数]
# 1、参数1,指定目录
#
# [调用说明]
# 1、未指定目录,则取当前目录:sh replace_class_header_anotation.sh
# 2、指定目录:sh replace_class_header_anotation.sh /User/xxx/xx
# 本脚本适用于将:下述注释替换成 统一注释模板:
# 其一:
#//
#// FileName.h
#// ProjectName
#//
#// Created by Author on Date.
#// (没版权信息)
#//
#
# 其二:
# /****************************************************************************************************
# * 版权所有: Copyright (c) 2012-2021 xxxx. All rights reserved.
# * 作 者: Author (2021/3/12)
# * 界面描述: 界面描述
# ****************************************************************************************************/
#
# 其三:
# 没有任何注释的
#
#
# 替换成统一注释模板:
#
#//
#// "$filename"
#// "$project_name"
#//
#// Created by "$auth" on "$date".
#// "$copyright_str"
#//
#
#定义版权信息
export copyright_str="Copyright (C) $(date +%Y) Your CompanyName Limited. All rights reserved."
#定义默认用户信息:PaysonChen
export def_author_str="PaysonChen"
#定义默认日期:当前日期
export def_time_str=`date +%Y/%m/%d`
function get_creator_name_with_template_2() {
file=$1
creator_name=$(sed -n 's/.*作 者: \(.*\).*/\1/p' $file)
echo "creator_name="$creator_name" in file="$file
if [ -z "$creator_name" ]; then
echo '///获取创建者 第二种模板获取 为空 使用默认值'
creator_name=$def_author_str
fi
}
function get_creator_name() {
file=$1
creator_name=$(sed -n 's/.*Created by \(.*\) on.*/\1/p' $file)
if [ -z "$creator_name" ]; then
get_creator_name_with_template_2 $file
fi
echo "--------creator_name=【"$creator_name"】 in file="$file
}
function get_creator_time_with_template_2() {
file=$1
creator_time=$(sed -n 's/.*创建日期: \(.*\).*/\1/p' $file)
echo "-------创建日期=【"$creator_time"】 in file="$file
if [ -z "$creator_time" ]; then
# echo '///获取创建时间 第二种模板获取 为空 使用默认值'
creator_time=$def_time_str
fi
}
function format_creator_time() {
creator_time=$1
length=${#creator_time}
# 截取除最后一个字符外的部分
creator_time=${creator_time:0:length-1}
#echo "截去掉最后一个字符后的字符串: $creator_time"
}
function get_creator_time() {
file=$1
if [ -z "$2" ]; then
line=5
else
line=$2
fi
#creator_time=$(sed -n '5s/.*\(.\{10\}\)$/\1/p' $file)
creator_time=$(awk 'NR=='$line' {print $NF}' $file)
echo "-------creator_time=【"$creator_time"】 line = "$line" in file="$file
# date_regex='^(19|20)[0-9]{2}/(0?[1-9]|1[0-2])/(0?[1-9]|[1-2][0-9]|3[0-1]).$'
#date_regex='^(19[0-9]{2}|20[0-9]{2}|[0-9]{2})/(0?[1-9]|1[0-2])/(0?[1-9]|[1-2][0-9]|3[0-1]).$'
date_regex='^(19[0-9]{2}|20[0-9]{2}|[0-9]{2})([-/])(0?[1-9]|1[0-2])([-/])(0?[1-9]|[1-2][0-9]|3[0-1]).$'
# 进行正则匹配
if [[ $creator_time =~ $date_regex ]]; then
echo "日期格式正确,截断最后一个小数 ."
format_creator_time $creator_time
else
if [ -z "$2" ]; then
discount=1
new_line=$((line-discount))
echo "常规调用如果匹配不到的花,那么多一次,向上查找"$discount"行,进行递归:"$new_line
get_creator_time $file $new_line
else
echo "日期格式错误,执行第二种匹配"
get_creator_time_with_template_2 $file
fi
fi
echo "********creator_time=【"$creator_time"】 in file="$file
}
function replace_header_anoation() {
file=$1
#定义要替换的字符串
#文件名
filename=$(echo "$file" | sed 's#.*/##')
#项目名
project_name="YourProjectName"
#还有从当前类中获取作者信息,获取不到取默认值
auth=$creator_name
#还有从当前类中获取作者信息,获取不到取默认值
date=$creator_time
#以下是替换的模板
new_content="//
// "$filename"
// "$project_name"
//
// Created by "$auth" on "$date".
// "$copyright_str"
//"
new_content_escaped=$(echo "$new_content" | sed 's/$/\\/') # 转义换行符
sed -i '' -e "1,7c\\
$new_content_escaped" "$file"
#还有几个问题待优化
#1、如果开头没有注释,则会直接覆盖,或者注释不足7行的
#2、日期正则如果不是以 YYYY/MM/DD or YY/MM/DD 其中/和-都适用
#2.1但是兼容2023/8/1这样的个位数日期),
#2.2如果日期是8/1/23 这样会导致识别错误 会被替换成今天的日期
}
# 统一类头注释
function unify_header_anoation() {
file=$1
#还有从当前类中获取作者信息,获取不到取默认值
get_creator_name $file
#还有从当前类中获取作者信息,获取不到取默认值
get_creator_time $file
#不传第二个参数 则执行替换,传就不执行
if [ -z "$2" ]; then
replace_header_anoation $file
fi
}
function main() {
file_path=$1
if [ -z "$file_path" ]; then
echo '///未指定路径,file_path为. 当前路径'
file_path=.
fi
#遍历当前路径下所有oc类
find $file_path -type f -name "*.swift" -o -name "*.h" -o -name "*.m" | while read file; do
unify_header_anoation $file $2
done
}
main $1 $2
|