refactor: 迁移至 bashly CLI 与功能域模块结构

- CLI 定义迁移至 src/bashly.yml(bashly 1.4 生成参数解析),入口收敛为 src/root_command.sh
- 源码按功能域重组:config/storage/integrate/media/pipeline,消除扁平散落
- 新增零依赖测试框架 tests/(123 用例)与 CI 流水线(lint + test + build + 产物一致性)
- build.sh 支持版本单一来源注入与 --check 产物校验;新增 lint.sh(bash -n + shellcheck 零容忍)
- 删除旧单文件 media_organizer.sh 与旧扁平模块
This commit is contained in:
Shuery committed 2026-08-14 22:41:28 +08:00
1 parent d978a13a83
commit 0df07ad0ae
48 files changed
+5813 -6812

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
# shellcheck shell=bash
################################################################################
# 硬链接处理
################################################################################
# 判断源与目标是否为同一 inode(硬链接已存在)。
# 获取文件 inode(兼容 GNU/BSD/BusyBox stat)。
# 依次尝试:GNU stat -c '%i' -> BSD stat -f '%i' -> ls -i -> find -printf。
get_file_inode() {
local filepath="$1"
local inode
inode=$(stat -c '%i' "$filepath" 2>/dev/null)
[[ -n "$inode" ]] && {
echo "$inode"
return 0
}
inode=$(stat -f '%i' "$filepath" 2>/dev/null)
[[ -n "$inode" ]] && {
echo "$inode"
return 0
}
# ls -i 解析 inode 字段(BusyBox 可靠,stat/find -printf 可能不可用)
# shellcheck disable=SC2012
inode=$(ls -i "$filepath" 2>/dev/null | awk '{print $1}')
[[ -n "$inode" ]] && {
echo "$inode"
return 0
}
# GNU find 兜底:-printf 解析 inode
find "$filepath" -maxdepth 0 -printf '%i' 2>/dev/null
}
same_inode() {
local src="$1" dst="$2"
[[ ! -e "$dst" ]] && return 1
local src_inode dst_inode
src_inode=$(get_file_inode "$src")
dst_inode=$(get_file_inode "$dst")
[[ -z "$src_inode" || -z "$dst_inode" ]] && return 1
[[ "$src_inode" == "$dst_inode" ]]
}
# 创建硬链接;干运行模式下仅打印;目标已存在时直接替换(不备份)。
# 注:不做 .bak 备份——遗留的 .bak_* 文件会被 Jellyfin 当作媒体扫描,干扰刮削。
hardlink_or_dryrun() {
local src="$1" dst="$2"
if $DRY_RUN; then
_log 信息 "干运行:硬链接 '$src' -> '$dst'"
return 0
fi
if same_inode "$src" "$dst"; then
_log 跳过 "硬链接已存在,inode: $(stat -c '%i' "$src" 2>/dev/null)"
return 0
fi
# 目标已存在:直接替换(先删旧目标再建硬链接)
if [[ -e "$dst" ]]; then
# 安全保护:目标是目录(如误传根目录)时拒绝替换,避免误操作真实目录
if [[ -d "$dst" ]]; then
_log 错误 "目标是目录,拒绝替换: $dst"
return 1
fi
_log 信息 "目标已存在,直接替换: $dst"
rm -f "$dst"
fi
if ln "$src" "$dst"; then
_log 成功 "硬链接已创建"
return 0
else
_log 错误 "硬链接创建失败"
return 1
fi
}
################################################################################
# 错误处理
################################################################################
# 全局 ERR trap:记录出错行号后退出。
_handle_error() {
local line_num="$1"
_log 错误 "脚本在第 $line_num 行出错(错误码:$?)"
exit 1
}