Files
MediaOrganizer/src/lib/pipeline/link.sh
T
Shuery 0df07ad0ae 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 与旧扁平模块
2026-08-14 22:41:28 +08:00

91 lines
2.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
}